Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added none operation #1297

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion processors/filterprocessor/fields/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ type Operation string

const anyFieldOperation Operation = "any"
const allFieldOperation Operation = "all"
const noneFieldOperation Operation = "none"

// ValidFieldOperation returns true if the input is a valid operation
func ValidFieldOperation(input string) bool {
if input != string(anyFieldOperation) && input != string(allFieldOperation) {
if input != string(anyFieldOperation) && input != string(allFieldOperation) && input != string(noneFieldOperation) {
return false
}

Expand All @@ -33,6 +34,28 @@ func (f Filter) SearchAndFilter(input data.BlockData) (data.BlockData, error) {

var newPayset []transactions.SignedTxnInBlock
switch f.Op {
case noneFieldOperation:
for _, txn := range input.Payset {

allFalse := true
for _, fs := range f.Searchers {
b, err := fs.search(txn)
if err != nil {
return data.BlockData{}, err
}
Comment on lines +43 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like the only bit that isn't covered by the unit tests. What are the failure conditions which would cause the searcher to return an error? Is this conditional something that should never happen or it could happen if you provide an invalid pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just allows the searcher interface to propagate errors if the implementation needs to. A quick example is the microalgos searcher which can return an error if the field is not a microalgo type (sort of belt and suspenders, but I think it is useful).

if b {
allFalse = false
break
}
}

if allFalse {
newPayset = append(newPayset, txn)
}

}
break

case anyFieldOperation:
for _, txn := range input.Payset {
for _, fs := range f.Searchers {
Expand Down
135 changes: 135 additions & 0 deletions processors/filterprocessor/filter_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,141 @@ import (
"github.com/algorand/indexer/processors"
)

// TestFilterProcessor_Init_None
func TestFilterProcessor_Init_None(t *testing.T) {

sampleAddr1 := basics.Address{1}
sampleAddr2 := basics.Address{2}
sampleAddr3 := basics.Address{3}

sampleCfgStr := `---
filters:
- none:
- tag: sgnr
expression-type: exact
expression: "` + sampleAddr1.String() + `"
- tag: txn.asnd
expression-type: regex
expression: "` + sampleAddr3.String() + `"
- all:
- tag: txn.rcv
expression-type: regex
expression: "` + sampleAddr2.String() + `"
- tag: txn.snd
expression-type: exact
expression: "` + sampleAddr2.String() + `"
- any:
- tag: txn.aclose
expression-type: exact
expression: "` + sampleAddr2.String() + `"
- tag: txn.arcv
expression-type: regex
expression: "` + sampleAddr2.String() + `"
`

fpBuilder, err := processors.ProcessorBuilderByName(implementationName)
assert.NoError(t, err)

fp := fpBuilder.New()
err = fp.Init(context.Background(), &conduit.PipelineInitProvider{}, plugins.PluginConfig(sampleCfgStr), logrus.New())
assert.NoError(t, err)

bd := data.BlockData{}
bd.Payset = append(bd.Payset,

transactions.SignedTxnInBlock{
SignedTxnWithAD: transactions.SignedTxnWithAD{
SignedTxn: transactions.SignedTxn{
AuthAddr: sampleAddr1,
},
},
},
transactions.SignedTxnInBlock{
SignedTxnWithAD: transactions.SignedTxnWithAD{
SignedTxn: transactions.SignedTxn{
AuthAddr: sampleAddr1,
Txn: transactions.Transaction{
PaymentTxnFields: transactions.PaymentTxnFields{
Receiver: sampleAddr2,
},
Header: transactions.Header{
Sender: sampleAddr2,
},
AssetTransferTxnFields: transactions.AssetTransferTxnFields{
AssetCloseTo: sampleAddr2,
},
},
},
},
},
transactions.SignedTxnInBlock{
SignedTxnWithAD: transactions.SignedTxnWithAD{
SignedTxn: transactions.SignedTxn{
AuthAddr: sampleAddr1,
Txn: transactions.Transaction{
AssetTransferTxnFields: transactions.AssetTransferTxnFields{
AssetSender: sampleAddr3,
},
PaymentTxnFields: transactions.PaymentTxnFields{
Receiver: sampleAddr3,
},
},
},
},
},
transactions.SignedTxnInBlock{
SignedTxnWithAD: transactions.SignedTxnWithAD{
SignedTxn: transactions.SignedTxn{
AuthAddr: sampleAddr1,
Txn: transactions.Transaction{
PaymentTxnFields: transactions.PaymentTxnFields{
Receiver: sampleAddr2,
},
Header: transactions.Header{
Sender: sampleAddr2,
},
AssetTransferTxnFields: transactions.AssetTransferTxnFields{
AssetSender: sampleAddr3,
AssetCloseTo: sampleAddr2,
AssetReceiver: sampleAddr2,
},
},
},
},
},
// The one transaction that will be allowed through
transactions.SignedTxnInBlock{
SignedTxnWithAD: transactions.SignedTxnWithAD{
SignedTxn: transactions.SignedTxn{
AuthAddr: sampleAddr2,
Txn: transactions.Transaction{
PaymentTxnFields: transactions.PaymentTxnFields{
Receiver: sampleAddr2,
},
Header: transactions.Header{
Sender: sampleAddr2,
},
AssetTransferTxnFields: transactions.AssetTransferTxnFields{
AssetSender: sampleAddr1,
AssetCloseTo: sampleAddr2,
AssetReceiver: sampleAddr2,
},
},
},
},
},
)

output, err := fp.Process(bd)
assert.NoError(t, err)
assert.Equal(t, len(output.Payset), 1)
assert.Equal(t, output.Payset[0].SignedTxnWithAD.SignedTxn.Txn.PaymentTxnFields.Receiver, sampleAddr2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe assign the txn to a var and then assert equal on output.Payset[0] and that txn.

assert.Equal(t, output.Payset[0].SignedTxnWithAD.SignedTxn.Txn.Header.Sender, sampleAddr2)
assert.Equal(t, output.Payset[0].SignedTxnWithAD.SignedTxn.Txn.AssetTransferTxnFields.AssetSender, sampleAddr1)
assert.Equal(t, output.Payset[0].SignedTxnWithAD.SignedTxn.Txn.AssetTransferTxnFields.AssetCloseTo, sampleAddr2)
assert.Equal(t, output.Payset[0].SignedTxnWithAD.SignedTxn.Txn.AssetTransferTxnFields.AssetReceiver, sampleAddr2)
}

// TestFilterProcessor_Illegal tests that numerical operations won't occur on non-supported types
func TestFilterProcessor_Illegal(t *testing.T) {
tests := []struct {
Expand Down