go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/starlark/builtins/stacktrace_test.go (about)

     1  // Copyright 2018 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package builtins
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"go.starlark.net/starlark"
    22  
    23  	. "github.com/smartystreets/goconvey/convey"
    24  	. "go.chromium.org/luci/common/testing/assertions"
    25  )
    26  
    27  func TestStacktrace(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	runScript := func(code string) (string, error) {
    31  		out, err := starlark.ExecFile(&starlark.Thread{}, "main", code, starlark.StringDict{
    32  			"stacktrace": Stacktrace,
    33  		})
    34  		if err != nil {
    35  			return "", err
    36  		}
    37  		if s, ok := out["out"].(starlark.String); ok {
    38  			return NormalizeStacktrace(s.GoString()), nil
    39  		}
    40  		return "", fmt.Errorf("not a string: %s", out["out"])
    41  	}
    42  
    43  	Convey("Works", t, func() {
    44  		out, err := runScript(`
    45  def func1():
    46    return func2()
    47  
    48  def func2():
    49    return stacktrace()
    50  
    51  s = func1()
    52  
    53  out = str(s)
    54  `)
    55  		So(err, ShouldBeNil)
    56  		So(out, ShouldEqual, `Traceback (most recent call last):
    57    main: in <toplevel>
    58    main: in func1
    59    main: in func2
    60    <builtin>: in stacktrace
    61  `)
    62  	})
    63  
    64  	Convey("Skips frames", t, func() {
    65  		out, err := runScript(`
    66  def func1():
    67    return func2()
    68  
    69  def func2():
    70    return stacktrace(skip=2)
    71  
    72  out = str(func1())
    73  `)
    74  		So(err, ShouldBeNil)
    75  		So(out, ShouldEqual, `Traceback (most recent call last):
    76    main: in <toplevel>
    77    main: in func1
    78  `)
    79  	})
    80  
    81  	Convey("Fails if asked to skip too much", t, func() {
    82  		_, err := runScript(`
    83  def func1():
    84    return func2()
    85  
    86  def func2():
    87    return stacktrace(skip=5)
    88  
    89  out = str(func1())
    90  `)
    91  		So(err, ShouldErrLike, "stacktrace: the stack is not deep enough to skip 5 levels, has only 4 frames")
    92  	})
    93  
    94  	Convey("Fails on negative skip", t, func() {
    95  		_, err := runScript(`stacktrace(-1)`)
    96  		So(err, ShouldErrLike, "stacktrace: bad 'skip' value -1")
    97  	})
    98  
    99  	Convey("Fails on wrong type", t, func() {
   100  		_, err := runScript(`stacktrace('zzz')`)
   101  		So(err, ShouldErrLike, "stacktrace: for parameter skip: got string, want int")
   102  	})
   103  }
   104  
   105  func TestNormalizeStacktrace(t *testing.T) {
   106  	t.Parallel()
   107  
   108  	Convey("Works", t, func() {
   109  		in := `Traceback (most recent call last):
   110    main:8:1: in <toplevel>
   111    main:3:2: in func1
   112    main:6:3: in func2
   113    <builtin>: in stacktrace
   114  
   115    skipped line
   116  `
   117  		out := `Traceback (most recent call last):
   118    main: in <toplevel>
   119    main: in func1
   120    main: in func2
   121    <builtin>: in stacktrace
   122  
   123    skipped line
   124  `
   125  		So(NormalizeStacktrace(in), ShouldEqual, out)
   126  	})
   127  }