Skip to content

Commit

Permalink
test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronc committed Feb 26, 2024
1 parent bff1c32 commit fe45d70
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 86 deletions.
4 changes: 2 additions & 2 deletions proto/regen/ecocredit/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ service Msg {
// the scope of the provided credit class, the credits will be minted to the
// existing credit batch, otherwise the credits will be issued in a new credit
// batch. The new credit batch will be created under an existing project if a
// project with a matching reference id already exists within the scope of the
// credit class, otherwise a new project will be created.
// project with a matching reference id already exists, otherwise a new project
// will be created.
rpc BridgeReceive(MsgBridgeReceive) returns (MsgBridgeReceiveResponse);

// AddCreditType is a governance method that allows the addition of new
Expand Down
26 changes: 3 additions & 23 deletions x/ecocredit/base/keeper/features/msg_create_project.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Feature: CreateProject
- when the credit class exists
- when the admin is an allowed credit class issuer
- when the non-empty reference id is unique within the scope of the credit class
- the project sequence is updated
- the project properties are added
- the response includes the project id

Expand Down Expand Up @@ -55,26 +54,7 @@ Feature: CreateProject
Scenario: non-empty reference id is not unique within credit class
Given a project with project id "C01-001" and reference id "VCS-001"
When alice attempts to create a project with class id "C01" and reference id "VCS-001"
Then expect the error "a project with reference id VCS-001 already exists within this credit class: invalid request"

Rule: the project sequence is updated

Background:
Given a credit type with abbreviation "C"
And a credit class with class id "C01" and issuer alice
And a credit class with class id "C02" and issuer alice

Scenario: the project sequence is updated
Given a project sequence with class id "C01" and next sequence "1"
When alice attempts to create a project with class id "C01"
Then expect project sequence with class id "C01" and next sequence "2"

Scenario: the project sequence is not updated
Given a project sequence with class id "C01" and next sequence "1"
When alice attempts to create a project with class id "C02"
Then expect project sequence with class id "C01" and next sequence "1"

# no failing scenario - state transitions only occur upon successful message execution
Then expect the error "a project with reference id VCS-001 already exists: invalid request"

Rule: the project properties are added

Expand Down Expand Up @@ -115,7 +95,7 @@ Feature: CreateProject
Then expect the response
"""
{
"project_id": "C01-001"
"project_id": "P001"
}
"""

Expand All @@ -132,6 +112,6 @@ Feature: CreateProject
Then expect event with properties
"""
{
"project_id": "C01-001"
"project_id": "P001"
}
"""
19 changes: 9 additions & 10 deletions x/ecocredit/base/keeper/msg_create_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func (k Keeper) CreateProject(ctx context.Context, req *types.MsgCreateProject)
return nil, err
}

// check if non-empty reference id is unique within the scope of the credit class
err = k.verifyReferenceID(ctx, classInfo.Key, req.ReferenceId)
// check if non-empty reference id is unique across all projects
err = k.verifyReferenceID(ctx, req.ReferenceId)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -94,26 +94,25 @@ func (k Keeper) createNewProject(ctx context.Context) (*api.Project, string, err
return newProject, projectID, nil
}

// verifyReferenceID prevents multiple projects from having the same reference id within the
// scope of a credit class. We verify this here at the message server level rather than at the
// ORM level because reference id is optional and therefore multiple projects within the scope
// of a credit class can have an empty reference id (see BridgeReceive for more information)
func (k Keeper) verifyReferenceID(ctx context.Context, classKey uint64, referenceID string) error {
// verifyReferenceID prevents multiple projects from having the same reference id.
// We verify this here at the message server level rather than at the
// ORM level because reference id is optional any project can have an empty reference id.
// (see BridgeReceive for more information)
func (k Keeper) verifyReferenceID(ctx context.Context, referenceID string) error {
if referenceID == "" {
// reference id is optional so an empty reference id is valid
return nil
}

key := api.ProjectClassKeyReferenceIdIndexKey{}.WithClassKeyReferenceId(classKey, referenceID)
key := api.ProjectReferenceIdIndexKey{}.WithReferenceId(referenceID)
it, err := k.stateStore.ProjectTable().List(ctx, key)
if err != nil {
return err
}
defer it.Close()
if it.Next() {
return sdkerrors.ErrInvalidRequest.Wrapf(
"a project with reference id %s already exists within this credit class", referenceID,
)
"a project with reference id %s already exists", referenceID)
}

return nil
Expand Down
52 changes: 1 addition & 51 deletions x/ecocredit/base/keeper/msg_create_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package keeper

import (
"encoding/json"
"strconv"
"strings"
"testing"

"github.com/gogo/protobuf/jsonpb"
Expand Down Expand Up @@ -61,40 +59,12 @@ func (s *createProjectSuite) ACreditClassWithClassIdAndIssuerAlice(a string) {
require.NoError(s.t, err)
}

func (s *createProjectSuite) AProjectSequenceWithClassIdAndNextSequence(a, b string) {
class, err := s.k.stateStore.ClassTable().GetById(s.ctx, a)
require.NoError(s.t, err)

nextSequence, err := strconv.ParseUint(b, 10, 32)
require.NoError(s.t, err)

err = s.k.stateStore.ProjectSequenceTable().Insert(s.ctx, &api.ProjectSequence{
ClassKey: class.Key,
NextSequence: nextSequence,
})
require.NoError(s.t, err)
}

func (s *createProjectSuite) AProjectWithProjectIdAndReferenceId(a, b string) {
classID := base.GetClassIDFromLegacyProjectID(a)

class, err := s.k.stateStore.ClassTable().GetById(s.ctx, classID)
require.NoError(s.t, err)

err = s.k.stateStore.ProjectTable().Insert(s.ctx, &api.Project{
err := s.k.stateStore.ProjectTable().Insert(s.ctx, &api.Project{
Id: a,
ReferenceId: b,
})
require.NoError(s.t, err)

seq := s.getProjectSequence(a)

// Save because project sequence may already exist
err = s.k.stateStore.ProjectSequenceTable().Save(s.ctx, &api.ProjectSequence{
ClassKey: class.Key,
NextSequence: seq + 1,
})
require.NoError(s.t, err)
}

func (s *createProjectSuite) AliceAttemptsToCreateAProjectWithClassId(a string) {
Expand Down Expand Up @@ -145,19 +115,6 @@ func (s *createProjectSuite) ExpectErrorContains(a string) {
require.ErrorContains(s.t, s.err, a)
}

func (s *createProjectSuite) ExpectProjectSequenceWithClassIdAndNextSequence(a string, b string) {
project, err := s.stateStore.ClassTable().GetById(s.ctx, a)
require.NoError(s.t, err)

nextSequence, err := strconv.ParseUint(b, 10, 64)
require.NoError(s.t, err)

projectSequence, err := s.stateStore.ProjectSequenceTable().Get(s.ctx, project.Key)
require.NoError(s.t, err)

require.Equal(s.t, nextSequence, projectSequence.NextSequence)
}

func (s *createProjectSuite) ExpectProjectProperties(a gocuke.DocString) {
var expected types.Project
err := jsonpb.UnmarshalString(a.Content, &expected)
Expand Down Expand Up @@ -190,10 +147,3 @@ func (s *createProjectSuite) ExpectEventWithProperties(a gocuke.DocString) {
err = testutil.MatchEvent(&event, sdkEvent)
require.NoError(s.t, err)
}

func (s *createProjectSuite) getProjectSequence(projectID string) uint64 {
str := strings.Split(projectID, "-")
seq, err := strconv.ParseUint(str[1], 10, 32)
require.NoError(s.t, err)
return seq
}

0 comments on commit fe45d70

Please sign in to comment.