1// Copyright 2023 The Gitea Authors. All rights reserved.2// SPDX-License-Identifier: MIT34package report56import (7 "context"8 "strings"9 "testing"10 "time"1112 runnerv1 "code.gitea.io/actions-proto-go/runner/v1"13 connect_go "connectrpc.com/connect"14 log "github.com/sirupsen/logrus"15 "github.com/stretchr/testify/assert"16 "github.com/stretchr/testify/mock"17 "github.com/stretchr/testify/require"18 "google.golang.org/protobuf/types/known/structpb"1920 "gitea.com/gitea/act_runner/internal/pkg/client/mocks"21)2223func TestReporter_parseLogRow(t *testing.T) {24 tests := []struct {25 name string26 debugOutputEnabled bool27 args []string28 want []string29 }{30 {31 "No command", false,32 []string{"Hello, world!"},33 []string{"Hello, world!"},34 },35 {36 "Add-mask", false,37 []string{38 "foo mysecret bar",39 "::add-mask::mysecret",40 "foo mysecret bar",41 },42 []string{43 "foo mysecret bar",44 "<nil>",45 "foo *** bar",46 },47 },48 {49 "Debug enabled", true,50 []string{51 "::debug::GitHub Actions runtime token access controls",52 },53 []string{54 "GitHub Actions runtime token access controls",55 },56 },57 {58 "Debug not enabled", false,59 []string{60 "::debug::GitHub Actions runtime token access controls",61 },62 []string{63 "<nil>",64 },65 },66 {67 "notice", false,68 []string{69 "::notice file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",70 },71 []string{72 "::notice file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",73 },74 },75 {76 "warning", false,77 []string{78 "::warning file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",79 },80 []string{81 "::warning file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",82 },83 },84 {85 "error", false,86 []string{87 "::error file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",88 },89 []string{90 "::error file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",91 },92 },93 {94 "group", false,95 []string{96 "::group::",97 "::endgroup::",98 },99 []string{100 "##[group]",101 "##[endgroup]",102 },103 },104 {105 "stop-commands", false,106 []string{107 "::add-mask::foo",108 "::stop-commands::myverycoolstoptoken",109 "::add-mask::bar",110 "::debug::Stuff",111 "myverycoolstoptoken",112 "::add-mask::baz",113 "::myverycoolstoptoken::",114 "::add-mask::wibble",115 "foo bar baz wibble",116 },117 []string{118 "<nil>",119 "<nil>",120 "::add-mask::bar",121 "::debug::Stuff",122 "myverycoolstoptoken",123 "::add-mask::baz",124 "<nil>",125 "<nil>",126 "*** bar baz ***",127 },128 },129 {130 "unknown command", false,131 []string{132 "::set-mask::foo",133 },134 []string{135 "::set-mask::foo",136 },137 },138 }139 for _, tt := range tests {140 t.Run(tt.name, func(t *testing.T) {141 r := &Reporter{142 logReplacer: strings.NewReplacer(),143 debugOutputEnabled: tt.debugOutputEnabled,144 }145 for idx, arg := range tt.args {146 rv := r.parseLogRow(&log.Entry{Message: arg})147 got := "<nil>"148149 if rv != nil {150 got = rv.Content151 }152153 assert.Equal(t, tt.want[idx], got)154 }155 })156 }157}158159func TestReporter_Fire(t *testing.T) {160 t.Run("ignore command lines", func(t *testing.T) {161 client := mocks.NewClient(t)162 client.On("UpdateLog", mock.Anything, mock.Anything).Return(func(_ context.Context, req *connect_go.Request[runnerv1.UpdateLogRequest]) (*connect_go.Response[runnerv1.UpdateLogResponse], error) {163 t.Logf("Received UpdateLog: %s", req.Msg.String())164 return connect_go.NewResponse(&runnerv1.UpdateLogResponse{165 AckIndex: req.Msg.Index + int64(len(req.Msg.Rows)),166 }), nil167 })168 client.On("UpdateTask", mock.Anything, mock.Anything).Return(func(_ context.Context, req *connect_go.Request[runnerv1.UpdateTaskRequest]) (*connect_go.Response[runnerv1.UpdateTaskResponse], error) {169 t.Logf("Received UpdateTask: %s", req.Msg.String())170 return connect_go.NewResponse(&runnerv1.UpdateTaskResponse{}), nil171 })172 ctx, cancel := context.WithCancel(context.Background())173 taskCtx, err := structpb.NewStruct(map[string]interface{}{})174 require.NoError(t, err)175 reporter := NewReporter(ctx, cancel, client, &runnerv1.Task{176 Context: taskCtx,177 }, time.Second)178 defer func() {179 assert.NoError(t, reporter.Close(""))180 }()181 reporter.ResetSteps(5)182183 dataStep0 := map[string]interface{}{184 "stage": "Main",185 "stepNumber": 0,186 "raw_output": true,187 }188189 assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))190 assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))191 assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))192 assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))193 assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))194 assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))195196 assert.Equal(t, int64(3), reporter.state.Steps[0].LogLength)197 })198}