Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdrag00nv2 committed Jun 25, 2023
1 parent 9813453 commit dbfae7e
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 55 deletions.
2 changes: 1 addition & 1 deletion runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -15192,7 +15192,7 @@ func NewUnmeteredCompositeField(name string, value Value) CompositeField {
// Create a CompositeValue with the provided StaticType.
// Useful when we wish to utilize CompositeValue as the value
// for a type which isn't CompositeType.
// For e.g. RangeType
// For e.g. InclusiveRangeType
func NewCompositeValueWithStaticType(
interpreter *Interpreter,
locationRange LocationRange,
Expand Down
17 changes: 2 additions & 15 deletions runtime/interpreter/value_range.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func NewInclusiveRangeValueWithStep(
Value: start,
},
{
Name: sema.InclusiveRangeTypeEndInclusiveFieldName,
Name: sema.InclusiveRangeTypeEndFieldName,
Value: end,
},
{
Expand All @@ -112,19 +112,6 @@ func NewInclusiveRangeValueWithStep(
rangeType,
)

rangeValue.ComputedFields = map[string]ComputedField{
sema.InclusiveRangeTypeCountFieldName: func(interpreter *Interpreter, locationRange LocationRange) Value {
start := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeStartFieldName)
endInclusive := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeEndInclusiveFieldName)
step := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeStepFieldName)

diff := convertAndAssertIntegerValue(endInclusive.Minus(interpreter, start, locationRange))

// Perform integer division & drop the decimal part.
// Note that step is guaranteed to be non-zero.
return diff.Div(interpreter, step, locationRange)
},
}
rangeValue.Functions = map[string]FunctionValue{
sema.InclusiveRangeTypeContainsFunctionName: NewHostFunctionValue(
interpreter,
Expand Down Expand Up @@ -158,7 +145,7 @@ func rangeContains(
needleValue Value,
) BoolValue {
start := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeStartFieldName)
endInclusive := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeEndInclusiveFieldName)
endInclusive := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeEndFieldName)
step := getFieldAsIntegerValue(rangeValue, interpreter, locationRange, sema.InclusiveRangeTypeStepFieldName)

needleInteger := convertAndAssertIntegerValue(needleValue)
Expand Down
43 changes: 36 additions & 7 deletions runtime/sema/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -5089,12 +5089,17 @@ func (r *InclusiveRangeType) RewriteWithRestrictedTypes() (Type, bool) {
}

const InclusiveRangeTypeStartFieldName = "start"
const InclusiveRangeTypeEndInclusiveFieldName = "endInclusive"
const InclusiveRangeTypeStepFieldName = "step"
const InclusiveRangeTypeCountFieldName = "count"
const inclusiveRangeTypeStartFieldDocString = `
The start of the InclusiveRange sequence
`
const InclusiveRangeTypeEndFieldName = "end"
const inclusiveRangeTypeEndFieldDocString = `
The end of the InclusiveRange sequence
`

const inclusiveRangeTypeCountFieldDocString = `
The number of entries in the Range sequence
const InclusiveRangeTypeStepFieldName = "step"
const inclusiveRangeTypeStepFieldDocString = `
The step size of the InclusiveRange sequence
`

const InclusiveRangeTypeContainsFunctionName = "contains"
Expand Down Expand Up @@ -5126,15 +5131,39 @@ func InclusiveRangeContainsFunctionType(elementType Type) *FunctionType {
func (r *InclusiveRangeType) initializeMemberResolvers() {
r.memberResolversOnce.Do(func() {
r.memberResolvers = withBuiltinMembers(r, map[string]MemberResolver{
InclusiveRangeTypeCountFieldName: {
InclusiveRangeTypeStartFieldName: {
Kind: common.DeclarationKindField,
Resolve: func(memoryGauge common.MemoryGauge, identifier string, _ ast.Range, _ func(error)) *Member {
return NewPublicConstantFieldMember(
memoryGauge,
r,
identifier,
r.ElementType(false),
inclusiveRangeTypeStartFieldDocString,
)
},
},
InclusiveRangeTypeEndFieldName: {
Kind: common.DeclarationKindField,
Resolve: func(memoryGauge common.MemoryGauge, identifier string, _ ast.Range, _ func(error)) *Member {
return NewPublicConstantFieldMember(
memoryGauge,
r,
identifier,
r.ElementType(false),
inclusiveRangeTypeEndFieldDocString,
)
},
},
InclusiveRangeTypeStepFieldName: {
Kind: common.DeclarationKindField,
Resolve: func(memoryGauge common.MemoryGauge, identifier string, _ ast.Range, _ func(error)) *Member {
return NewPublicConstantFieldMember(
memoryGauge,
r,
identifier,
r.ElementType(false),
inclusiveRangeTypeCountFieldDocString,
inclusiveRangeTypeStepFieldDocString,
)
},
},
Expand Down
245 changes: 213 additions & 32 deletions runtime/tests/checker/range_value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,226 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/onflow/cadence/runtime/sema"
"github.com/onflow/cadence/runtime/stdlib"
)

func TestInclusiveRange(t *testing.T) {
type inclusiveRangeConstructionTest struct {
ty sema.Type
s, e, step int64
}

func TestInclusiveRangeConstruction(t *testing.T) {
t.Parallel()

baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation)
baseValueActivation.DeclareValue(stdlib.InclusiveRangeConstructorFunction)

runValidCase := func(t *testing.T, memberType sema.Type, withStep bool) {
t.Run(memberType.String(), func(t *testing.T) {
validTestCases := []inclusiveRangeConstructionTest{
// Int*
{
ty: sema.IntType,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.IntType,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int8Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int8Type,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int16Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int16Type,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int32Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int32Type,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int64Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int64Type,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int128Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int128Type,
s: 10,
e: -10,
step: -2,
},
{
ty: sema.Int256Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Int256Type,
s: 10,
e: -10,
step: -2,
},

// UInt*
{
ty: sema.UIntType,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt8Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt16Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt32Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt64Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt128Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.UInt256Type,
s: 0,
e: 10,
step: 2,
},

// Word*
{
ty: sema.Word8Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Word16Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Word32Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Word64Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Word128Type,
s: 0,
e: 10,
step: 2,
},
{
ty: sema.Word256Type,
s: 0,
e: 10,
step: 2,
},
}

runValidCase := func(t *testing.T, testCase inclusiveRangeConstructionTest, withStep bool) {
t.Run(testCase.ty.String(), func(t *testing.T) {
t.Parallel()

var code string
if withStep {
code = fmt.Sprintf(
`
let s : %s = 10
let e : %s = 20
let step : %s = 2
let s : %s = %d
let e : %s = %d
let step : %s = %d
let r = InclusiveRange(s, e, step: step)
let rs = r.start
let re = r.end
let rstep = r.step
let contains_res = r.contains(s)
`,
memberType.String(), memberType.String(), memberType.String())
testCase.ty.String(), testCase.s, testCase.ty.String(), testCase.e, testCase.ty.String(), testCase.step)
} else {
code = fmt.Sprintf(
`
let s : %s = 10
let e : %s = 20
let s : %s = %d
let e : %s = %d
let r = InclusiveRange(s, e)
let rs = r.start
let re = r.end
let rstep = r.step
let contains_res = r.contains(s)
`,
memberType.String(), memberType.String())
testCase.ty.String(), testCase.s, testCase.ty.String(), testCase.e)
}

checker, err := ParseAndCheckWithOptions(t, code,
Expand All @@ -67,30 +253,25 @@ func TestInclusiveRange(t *testing.T) {
)

require.NoError(t, err)
resType := RequireGlobalValue(t, checker.Elaboration, "r")
require.Equal(t,
&sema.InclusiveRangeType{
MemberType: memberType,
},
resType,
)
})
}

runValidCaseWithoutStep := func(t *testing.T, memberType sema.Type) {
runValidCase(t, memberType, false)
}
runValidCaseWithStep := func(t *testing.T, memberType sema.Type) {
runValidCase(t, memberType, true)
}
checkType := func(t *testing.T, name string, expectedType sema.Type) {
resType := RequireGlobalValue(t, checker.Elaboration, name)
assert.IsType(t, expectedType, resType)
}

for _, integerType := range sema.AllIntegerTypes {
switch integerType {
case sema.IntegerType, sema.SignedIntegerType:
continue
}
checkType(t, "r", &sema.InclusiveRangeType{
MemberType: testCase.ty,
})
checkType(t, "rs", testCase.ty)
checkType(t, "re", testCase.ty)
checkType(t, "rstep", testCase.ty)
checkType(t, "contains_res", sema.BoolType)
})
}

runValidCaseWithStep(t, integerType)
runValidCaseWithoutStep(t, integerType)
// Run each test case with and without step.
for _, testCase := range validTestCases {
runValidCase(t, testCase, true)
runValidCase(t, testCase, false)
}
}

0 comments on commit dbfae7e

Please sign in to comment.