lostluck commented on a change in pull request #15206:
URL: https://github.com/apache/beam/pull/15206#discussion_r675716887



##########
File path: sdks/go/pkg/beam/core/runtime/exec/util_test.go
##########
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+       "context"
+       "strings"
+       "testing"
+
+       "github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
+       "github.com/apache/beam/sdks/go/pkg/beam/util/errorx"
+)
+
+// testSimpleError tests for a simple case that
+// doesn't panic
+func TestCallNoPanic_simple(t *testing.T) {
+       ctx := context.Background()
+       expected := errors.New("Simple error.")
+       actual := callNoPanic(ctx, func(c context.Context) error { return 
errors.New("Simple error.") })

Review comment:
       Style nit: In go we use "got" and "want" rather than actual, expected. 
They're shorter, which makes them easier to read.

##########
File path: sdks/go/pkg/beam/core/runtime/exec/util.go
##########
@@ -33,13 +34,29 @@ func (g *GenID) New() UnitID {
        return UnitID(g.last)
 }
 
+type doFnError struct {
+       doFn string
+       err  error
+       uid  UnitID
+       pid  string
+}
+
+func (e *doFnError) Error() string {
+       return fmt.Sprintf("DoFn[<%d>;<%s>]<%s> returned error:<%s>", e.uid, 
e.pid, e.doFn, e.err)
+}
+
 // callNoPanic calls the given function and catches any panic.
 func callNoPanic(ctx context.Context, fn func(context.Context) error) (err 
error) {
        defer func() {
                if r := recover(); r != nil {
-                       // Top level error is the panic itself, but also 
include the stack trace as the original error.
-                       // Higher levels can then add appropriate context 
without getting pushed down by the stack trace.
-                       err = errors.SetTopLevelMsgf(errors.Errorf("panic: %v 
%s", r, debug.Stack()), "panic: %v", r)
+                       // Check if the panic value is from a failed DoFn, and 
return it without a pancic trace.
+                       if e, ok := r.(doFnError); ok {

Review comment:
       I don't think this line runs as expected: in the fail() call in pardo.go 
it's passed a *doFnError to the guarded error, but then it's type asserting the 
recovery value here as the non-pointer type.  And then in the _wrappedPanic 
case, a non-pointer doFnError is used instead of the pointer, not replicating 
what's happening in fail.

##########
File path: sdks/go/pkg/beam/core/runtime/exec/util_test.go
##########
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+       "context"
+       "strings"
+       "testing"
+
+       "github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
+       "github.com/apache/beam/sdks/go/pkg/beam/util/errorx"
+)
+
+// testSimpleError tests for a simple case that
+// doesn't panic
+func TestCallNoPanic_simple(t *testing.T) {
+       ctx := context.Background()
+       expected := errors.New("Simple error.")
+       actual := callNoPanic(ctx, func(c context.Context) error { return 
errors.New("Simple error.") })
+
+       if actual.Error() != expected.Error() {
+               t.Errorf("Simple error reporting failed.")

Review comment:
       Test error messages should identify the function under test, and the 
inputs to that function. In this case consider changing it to:
   
   `t.Errorf("callNoPanic(<func that returns error>) = %v, want %v", got, want)`
   
   The inputs here are more than we want to write (function pointers don't have 
a meaninful thing to print), but the specifics don't matter in this case, just 
that the function actually returns an error.

##########
File path: sdks/go/pkg/beam/core/runtime/exec/util_test.go
##########
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+       "context"
+       "strings"
+       "testing"
+
+       "github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
+       "github.com/apache/beam/sdks/go/pkg/beam/util/errorx"
+)
+
+// testSimpleError tests for a simple case that
+// doesn't panic
+func TestCallNoPanic_simple(t *testing.T) {
+       ctx := context.Background()
+       expected := errors.New("Simple error.")
+       actual := callNoPanic(ctx, func(c context.Context) error { return 
errors.New("Simple error.") })
+
+       if actual.Error() != expected.Error() {
+               t.Errorf("Simple error reporting failed.")
+       }
+}
+
+// testPanicError tests for the case in which a normal
+// error is passed to panic, resulting in panic trace.
+func TestCallNoPanic_panic(t *testing.T) {
+       ctx := context.Background()
+       actual := callNoPanic(ctx, func(c context.Context) error { panic("Panic 
error") })
+       if !strings.Contains(actual.Error(), "panic:") {
+               t.Errorf("Panic reporting failed.")

Review comment:
       Similarly:
   `t.Errorf("callNoPanic(<func that panics with a string>) didn't contain 
panic, got = %v", got)`
   
   Note that in this case since we know the panic trace could be very long, or 
mis formatted, it's better to indicate the expectation before including what we 
actually got.

##########
File path: sdks/go/pkg/beam/core/runtime/exec/util_test.go
##########
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+       "context"
+       "strings"
+       "testing"
+
+       "github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
+       "github.com/apache/beam/sdks/go/pkg/beam/util/errorx"
+)
+
+// testSimpleError tests for a simple case that
+// doesn't panic
+func TestCallNoPanic_simple(t *testing.T) {
+       ctx := context.Background()
+       expected := errors.New("Simple error.")
+       actual := callNoPanic(ctx, func(c context.Context) error { return 
errors.New("Simple error.") })
+
+       if actual.Error() != expected.Error() {
+               t.Errorf("Simple error reporting failed.")
+       }
+}
+
+// testPanicError tests for the case in which a normal
+// error is passed to panic, resulting in panic trace.
+func TestCallNoPanic_panic(t *testing.T) {
+       ctx := context.Background()
+       actual := callNoPanic(ctx, func(c context.Context) error { panic("Panic 
error") })
+       if !strings.Contains(actual.Error(), "panic:") {
+               t.Errorf("Panic reporting failed.")
+       }
+}
+
+// testWrapPanicError tests for the case in which error
+// is passed to panic from DoFn, resulting in
+// formatted error message for DoFn.
+func TestCallNoPanic_wrappedPanic(t *testing.T) {
+       ctx := context.Background()
+       parDoError := doFnError{
+               doFn: "sumFn",
+               err:  errors.New("SumFn error"),
+               uid:  1,
+               pid:  "Plan ID",
+       }
+       var err errorx.GuardedError
+       err.TrySetError(&parDoError)
+       actual := callNoPanic(ctx, func(c context.Context) error { 
panic(parDoError) })
+
+       if strings.Contains(actual.Error(), "panic:") {
+               t.Errorf("Error not wrapped! Caught in panic.")

Review comment:
       Similarly:
   `t.Errorf("callNoPanic(<func that panics with a wrapped known error>) did 
not filter panic, want %v, got %", want, got)`
   
   Usually test messages should match the "simple" case above, with the got 
coming before the want. However, in this case, since we know the got will be 
longer to print out when this test fails (since it presumably has a panic 
trace), it's better to print the want before the got.

##########
File path: sdks/go/pkg/beam/core/runtime/exec/util_test.go
##########
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package exec
+
+import (
+       "context"
+       "strings"
+       "testing"
+
+       "github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
+       "github.com/apache/beam/sdks/go/pkg/beam/util/errorx"
+)
+
+// testSimpleError tests for a simple case that
+// doesn't panic
+func TestCallNoPanic_simple(t *testing.T) {
+       ctx := context.Background()
+       expected := errors.New("Simple error.")
+       actual := callNoPanic(ctx, func(c context.Context) error { return 
errors.New("Simple error.") })
+
+       if actual.Error() != expected.Error() {
+               t.Errorf("Simple error reporting failed.")
+       }
+}
+
+// testPanicError tests for the case in which a normal
+// error is passed to panic, resulting in panic trace.
+func TestCallNoPanic_panic(t *testing.T) {
+       ctx := context.Background()
+       actual := callNoPanic(ctx, func(c context.Context) error { panic("Panic 
error") })
+       if !strings.Contains(actual.Error(), "panic:") {
+               t.Errorf("Panic reporting failed.")
+       }
+}
+
+// testWrapPanicError tests for the case in which error
+// is passed to panic from DoFn, resulting in
+// formatted error message for DoFn.
+func TestCallNoPanic_wrappedPanic(t *testing.T) {
+       ctx := context.Background()
+       parDoError := doFnError{

Review comment:
       Make it a pointer type here, and remove the & passed to the TrySetError 
call.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to