github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/output/stream_test.go (about)

     1  package output
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/csv"
     6  	"encoding/json"
     7  	"fmt"
     8  	"testing"
     9  	"text/template"
    10  
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    12  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
    13  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
    14  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/utils"
    15  )
    16  
    17  var input = types.Receipt{
    18  	BlockHash:         base.HexToHash("0x123"),
    19  	BlockNumber:       123,
    20  	ContractAddress:   base.HexToAddress("0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5"),
    21  	CumulativeGasUsed: 500,
    22  	From:              base.HexToAddress("0xfd4536dd5a81ecfd1a4b30111a01d129e7567ff8"),
    23  	GasUsed:           500,
    24  	EffectiveGasPrice: 500,
    25  	Logs: []types.Log{
    26  		{
    27  			Address:          base.HexToAddress("0x02ef66278c3c88ff929a5c84c46fbfb83614382e"),
    28  			LogIndex:         0,
    29  			BlockNumber:      124,
    30  			TransactionIndex: 1,
    31  		},
    32  	},
    33  	Status:           1,
    34  	IsError:          false,
    35  	To:               base.HexToAddress("0x917e5e52ac55098d8caa1709e33178aadd9d4901"),
    36  	TransactionHash:  base.HexToHash("0x124"),
    37  	TransactionIndex: 1,
    38  }
    39  
    40  func helperStreamFormats(w csv.Writer, outputBuffer *bytes.Buffer, chain, format string, expectKeys bool) error {
    41  	buffer := new(bytes.Buffer)
    42  	StreamModel(buffer, input.Model(chain, format, false, nil), OutputOptions{
    43  		Format:   format,
    44  		NoHeader: !expectKeys,
    45  	})
    46  	result := buffer.String()
    47  
    48  	var expectedItems []string
    49  	data := input.Model(chain, format, false, nil).Data
    50  	for _, key := range input.Model(chain, format, false, nil).Order {
    51  		expectedItems = append(expectedItems, fmt.Sprint(data[key]))
    52  	}
    53  	if expectKeys {
    54  		w.Write(input.Model(chain, format, false, nil).Order)
    55  	}
    56  	w.Write(expectedItems)
    57  	w.Flush()
    58  	expected := outputBuffer.String()
    59  
    60  	if result != expected {
    61  		return fmt.Errorf("mismatch for format '%s': <%s>", format, result)
    62  	}
    63  	return nil
    64  }
    65  
    66  func TestStreamFormats(t *testing.T) {
    67  	chain := utils.GetTestChain()
    68  	outputBuffer := &bytes.Buffer{}
    69  	csvWriter := csv.NewWriter(outputBuffer)
    70  
    71  	err := helperStreamFormats(*csvWriter, outputBuffer, chain, "csv", false)
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  
    76  	csvWriter.Comma = '\t'
    77  	outputBuffer.Reset()
    78  	err = helperStreamFormats(*csvWriter, outputBuffer, chain, "txt", false)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	csvWriter.Comma = ':'
    84  	outputBuffer.Reset()
    85  	err = helperStreamFormats(*csvWriter, outputBuffer, chain, ":", false)
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  }
    90  
    91  func TestStreamJson(t *testing.T) {
    92  	chain := utils.GetTestChain()
    93  	outputBuffer := &bytes.Buffer{}
    94  	w := NewJsonWriter(outputBuffer)
    95  	w.DefaultField = DefaultField{Key: "Data", FieldType: FieldArray}
    96  	StreamModel(w, input.Model(chain, "json", false, nil), OutputOptions{
    97  		Format:     "json",
    98  		JsonIndent: "  ",
    99  	})
   100  	w.Close()
   101  	result := outputBuffer.String()
   102  	expected, err := json.MarshalIndent(struct {
   103  		Data []interface{}
   104  	}{
   105  		Data: []interface{}{input.Model(chain, "json", false, nil).Data},
   106  	}, "", "  ")
   107  
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	if result != string(expected) {
   112  		t.Fatal("mismatch in JSON format")
   113  	}
   114  }
   115  
   116  func TestStreamPrintKeys(t *testing.T) {
   117  	chain := utils.GetTestChain()
   118  	outputBuffer := &bytes.Buffer{}
   119  	csvWriter := csv.NewWriter(outputBuffer)
   120  
   121  	err := helperStreamFormats(*csvWriter, outputBuffer, chain, "csv", true)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  }
   126  
   127  func TestStreamTemplate(t *testing.T) {
   128  	chain := utils.GetTestChain()
   129  	tmpl := template.Must(template.New("").Parse("{{.blockNumber}} used {{.gasUsed}}{{if .Nonexistent}}111{{else}}.{{end}}"))
   130  	outputBuffer := &bytes.Buffer{}
   131  
   132  	err := StreamWithTemplate(outputBuffer, input.Model(chain, "", false, nil), tmpl)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	if outputBuffer.String() != "123 used 500." {
   137  		t.Fatal("mismatched template text:", outputBuffer.String())
   138  	}
   139  }
   140  
   141  func TestStreamMany(t *testing.T) {
   142  	buffer := &bytes.Buffer{}
   143  	jw := NewJsonWriter(buffer)
   144  	jw.DefaultField = DefaultField{
   145  		Key:       "data",
   146  		FieldType: FieldArray,
   147  	}
   148  
   149  	renderData := func(modelChan chan types.Modeler, errorChan chan error) {
   150  		modelChan <- &types.Receipt{
   151  			BlockNumber:      123,
   152  			TransactionIndex: 1,
   153  			TransactionHash:  base.HexToHash("0xdeadbeef"),
   154  			GasUsed:          100,
   155  			Status:           1,
   156  			IsError:          false,
   157  		}
   158  
   159  		modelChan <- &types.Receipt{
   160  			BlockNumber:      124,
   161  			TransactionIndex: 5,
   162  			TransactionHash:  base.HexToHash("0xdeadbeef2"),
   163  			GasUsed:          200,
   164  			Status:           1,
   165  			IsError:          false,
   166  		}
   167  	}
   168  
   169  	// Print the values and try to re-parse them to check if
   170  	// we get the same data
   171  	rCtx := NewRenderContext()
   172  	StreamMany(rCtx, renderData, OutputOptions{
   173  		Writer: jw,
   174  		Format: "json",
   175  	})
   176  	jw.Close()
   177  
   178  	type R = struct {
   179  		Data []types.Receipt `json:"data"`
   180  	}
   181  	var result R
   182  	err := json.Unmarshal(buffer.Bytes(), &result)
   183  	if err != nil {
   184  		logger.Error(buffer.String())
   185  		t.Fatal(err)
   186  	}
   187  
   188  	if result.Data[0].BlockNumber != 123 {
   189  		t.Fatal("mismatched data")
   190  	}
   191  	if result.Data[1].BlockNumber != 124 {
   192  		t.Fatal("mismatched data")
   193  	}
   194  }
   195  
   196  func TestApiFormat(t *testing.T) {
   197  	outputBuffer := &bytes.Buffer{}
   198  	fetchData := func(modelChan chan types.Modeler, errorChan chan error) {
   199  		modelChan <- &types.Receipt{
   200  			BlockNumber:      123,
   201  			TransactionIndex: 1,
   202  			TransactionHash:  base.HexToHash("0xdeadbeef"),
   203  			GasUsed:          100,
   204  			Status:           1,
   205  			IsError:          false,
   206  		}
   207  	}
   208  	rCtx := NewRenderContext()
   209  	err := StreamMany(rCtx, fetchData, OutputOptions{
   210  		Writer: outputBuffer,
   211  		Format: "api",
   212  	})
   213  	if err == nil {
   214  		t.Fatal("Api format is no longer allow. Should error here.")
   215  	}
   216  }