@@ -57,7 +57,7 @@ func TestNewDAO(t *testing.T) {
5757 }
5858 }
5959
60- urequire.Equal(t, 5 , dao.Core.ResourcesCount(), "expected 5 resources")
60+ urequire.Equal(t, 7 , dao.Core.ResourcesCount(), "expected 7 resources")
6161 urequire.Equal(t, dao.Realm.PkgPath(), daoRealm.PkgPath())
6262
6363 // XXX: check realm and profile
@@ -725,3 +725,125 @@ func newTestingDAO(t *testing.T, threshold float64, members []Member) *testingDA
725725 unknownProposalRequest: unknownProposalRequest,
726726 }
727727}
728+
729+ func TestAddRemoveResource(t *testing.T) {
730+ resourceType := "newResource"
731+ members := []Member{
732+ {
733+ alice.String(),
734+ []string{"admin"},
735+ },
736+ {
737+ bob.String(),
738+ []string{"admin"},
739+ },
740+ }
741+ tdao := newTestingDAO(t, 0.2, members)
742+
743+ if !tdao.dao.Members.HasRole(bob.String(), "admin") {
744+ t.Errorf("Expected member %s to have role 'admin'", bob.String())
745+ }
746+
747+ mockHandler := daokit.NewMessageHandler(resourceType, func(_ interface{}) {})
748+
749+ addResourceProposal := daokit.ProposalRequest{
750+ Title: "My Proposal",
751+ Description: "My Proposal Description",
752+ Message: daokit.NewSetResourceMsg(&daokit.Resource{
753+ Handler: mockHandler,
754+ Condition: daocond.MembersThreshold(0.2, tdao.dao.Members.IsMember, tdao.dao.Members.MembersCount),
755+ }),
756+ }
757+ urequire.Equal(t, 8, tdao.dao.Core.ResourcesCount(), "expected 8 resources")
758+ std.TestSetOrigCaller(alice)
759+ tdao.dao.InstantExecute(addResourceProposal)
760+ urequire.Equal(t, 9, tdao.dao.Core.ResourcesCount(), "expected 9 resources")
761+
762+ removeResourceProposal := daokit.ProposalRequest{
763+ Title: "My Proposal",
764+ Description: "My Proposal Description",
765+ Message: daokit.NewRemoveResourceMsg(&daokit.Resource{
766+ Handler: mockHandler,
767+ Condition: daocond.MembersThreshold(0.2, tdao.dao.Members.IsMember, tdao.dao.Members.MembersCount),
768+ }),
769+ }
770+
771+ tdao.dao.InstantExecute(removeResourceProposal)
772+
773+ urequire.Equal(t, 8, tdao.dao.Core.ResourcesCount(), "expected 8 resources")
774+ }
775+
776+ func TestAddRemoveResourceInvalidateProposals(t *testing.T) {
777+ resourceType := "newResource"
778+ members := []Member{
779+ {
780+ alice.String(),
781+ []string{"admin"},
782+ },
783+ {
784+ bob.String(),
785+ []string{"admin"},
786+ },
787+ }
788+ tdao := newTestingDAO(t, 0.2, members)
789+
790+ if !tdao.dao.Members.HasRole(bob.String(), "admin") {
791+ t.Errorf("Expected member %s to have role 'admin'", bob.String())
792+ }
793+
794+ mockHandler := daokit.NewMessageHandler(resourceType, func(_ interface{}) {})
795+
796+ addResourceProposal := daokit.ProposalRequest{
797+ Title: "My Proposal",
798+ Description: "My Proposal Description",
799+ Message: daokit.NewSetResourceMsg(&daokit.Resource{
800+ Handler: mockHandler,
801+ Condition: daocond.MembersThreshold(0.2, tdao.dao.Members.IsMember, tdao.dao.Members.MembersCount),
802+ }),
803+ }
804+ std.TestSetOrigCaller(alice)
805+ tdao.dao.InstantExecute(addResourceProposal)
806+
807+ proposalAddMember := daokit.ProposalRequest{
808+ Message: daokit.NewMessage(MsgAddMemberKind, nil),
809+ }
810+
811+ newResourceProposal := daokit.ProposalRequest{
812+ Message: daokit.NewMessage(resourceType, nil),
813+ }
814+
815+ tdao.dao.Propose(newResourceProposal)
816+ tdao.dao.Propose(proposalAddMember)
817+
818+ // Check proposal is open
819+ tdao.dao.Core.ProposalModule.Proposals.Iterate("", "", func(k string, v interface{}) bool {
820+ p := v.(*daokit.Proposal)
821+ if p.Message.Type() == resourceType {
822+ urequire.Equal(t, int(daokit.ProposalStatusOpen), int(p.Status), "expected to be open")
823+ } else if p.Message.Type() == MsgAddMemberKind {
824+ urequire.Equal(t, int(daokit.ProposalStatusOpen), int(p.Status), "expected to be open")
825+ }
826+ return false
827+ })
828+
829+ removeResourceProposal := daokit.ProposalRequest{
830+ Title: "removeResource",
831+ Description: "My Proposal Description",
832+ Message: daokit.NewRemoveResourceMsg(&daokit.Resource{
833+ Handler: mockHandler,
834+ Condition: daocond.MembersThreshold(0.2, tdao.dao.Members.IsMember, tdao.dao.Members.MembersCount),
835+ }),
836+ }
837+ tdao.dao.InstantExecute(removeResourceProposal)
838+
839+ // proposal should be invalidated
840+ tdao.dao.Core.ProposalModule.Proposals.Iterate("", "", func(k string, v interface{}) bool {
841+ p := v.(*daokit.Proposal)
842+ if p.Message.Type() == resourceType {
843+ urequire.Equal(t, int(daokit.ProposalStatusInvalidated), int(p.Status), "expected to be invalidated")
844+ } else if p.Message.Type() == MsgAddMemberKind {
845+ urequire.Equal(t, int(daokit.ProposalStatusOpen), int(p.Status), "expected to stay open")
846+ }
847+ return false
848+ })
849+ }
0 commit comments