<commit_before>//go:build !windows
// +build !windows

/*
   Copyright The containerd Authors.

   Licensed 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 integration

import (
	"context"
	"net"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	v1shimcli "github.com/containerd/containerd/runtime/v1/shim/client"
	v2shimcli "github.com/containerd/containerd/runtime/v2/shim"
	"github.com/containerd/ttrpc"
	"github.com/pkg/errors"
)

const abstractSocketPrefix = "\x00"

// TestFailFastWhenConnectShim is to test that the containerd task manager
// should not tolerate ENOENT during restarting. In linux, the containerd shim
// always listens on socket before task manager dial. If there is ENOENT or
// ECONNREFUSED error, the task manager should clean up because that socket file
// is gone or shim doesn't listen on the socket anymore.
func TestFailFastWhenConnectShim(t *testing.T) {
	t.Parallel()

	t.Run("abstract-unix-socket-v1", testFailFastWhenConnectShim(true, v1shimcli.AnonDialer))
	t.Run("abstract-unix-socket-v2", testFailFastWhenConnectShim(true, v2shimcli.AnonDialer))
	t.Run("normal-unix-socket-v1", testFailFastWhenConnectShim(false, v1shimcli.AnonDialer))
	t.Run("normal-unix-socket-v2", testFailFastWhenConnectShim(false, v2shimcli.AnonDialer))
}

type dialFunc func(address string, timeout time.Duration) (net.Conn, error)

func testFailFastWhenConnectShim(abstract bool, dialFn dialFunc) func(*testing.T) {
	return func(t *testing.T) {
		var (
			ctx                     = context.Background()
			addr, listener, cleanup = newTestListener(t, abstract)
			errCh                   = make(chan error, 1)

			checkDialErr = func(addr string, errCh chan error, expected error) {
				go func() {
					_, err := dialFn(addr, 1*time.Hour)
					errCh <- err
				}()

				select {
				case <-time.After(10 * time.Second):
					t.Fatalf("expected fail fast, but got timeout")
				case err := <-errCh:
					t.Helper()
					if !errors.Is(err, expected) {<commit_msg>fix: only test abstract unix socket on linux<commit_after>//go:build !windows
// +build !windows

/*
   Copyright The containerd Authors.

   Licensed 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 integration

import (
	"context"
	"net"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"testing"
	"time"

	v1shimcli "github.com/containerd/containerd/runtime/v1/shim/client"
	v2shimcli "github.com/containerd/containerd/runtime/v2/shim"
	"github.com/containerd/ttrpc"
	"github.com/pkg/errors"
)

const abstractSocketPrefix = "\x00"

// TestFailFastWhenConnectShim is to test that the containerd task manager
// should not tolerate ENOENT during restarting. In linux, the containerd shim
// always listens on socket before task manager dial. If there is ENOENT or
// ECONNREFUSED error, the task manager should clean up because that socket file
// is gone or shim doesn't listen on the socket anymore.
func TestFailFastWhenConnectShim(t *testing.T) {
	t.Parallel()

	// abstract Unix domain sockets are only for Linux.
	if runtime.GOOS == "linux" {
		t.Run("abstract-unix-socket-v1", testFailFastWhenConnectShim(true, v1shimcli.AnonDialer))
		t.Run("abstract-unix-socket-v2", testFailFastWhenConnectShim(true, v2shimcli.AnonDialer))
	}
	t.Run("normal-unix-socket-v1", testFailFastWhenConnectShim(false, v1shimcli.AnonDialer))
	t.Run("normal-unix-socket-v2", testFailFastWhenConnectShim(false, v2shimcli.AnonDialer))
}

type dialFunc func(address string, timeout time.Duration) (net.Conn, error)

func testFailFastWhenConnectShim(abstract bool, dialFn dialFunc) func(*testing.T) {
	return func(t *testing.T) {
		var (
			ctx                     = context.Background()
			addr, listener, cleanup = newTestListener(t, abstract)
			errCh                   = make(chan error, 1)

			checkDialErr = func(addr string, errCh chan error, expected error) {
				go func() {
					_, err := dialFn(addr, 1*time.Hour)
					errCh <- err
				}()

				select {
				case <-time.After(10 * time.Second):
					t.Fatalf("expected fail fast, but got timeout")
				case err := <-errCh:
					t.Helper()
					if !errors.Is(err, expected) {
{'fraction_non_alphanumeric': 0.1017578125, 'fraction_numerical': 0.00859375, 'mean_word_length': 3.77705223880597, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '953821', 'n_tokens_mistral': 1751, 'n_tokens_neox': 1621, 'n_words': 495}