You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: postupgrade_test.go
    path of file: ./repos/kubernetes/cmd/kubeadm/app/phases/upgrade
    
    the code of the file until where you have to start completion: /*
Copyright 2017 The Kubernetes 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 upgrade

import (
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"testing"

	"github.com/pkg/errors"

	errorsutil "k8s.io/apimachinery/pkg/util/errors"
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
	"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
	"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
	testutil "k8s.io/kubernetes/cmd/kubeadm/test"
)

func TestMo
    
func TestWriteKubeletConfigFiles(t *testing.T) {
	// exit early if the user doesn't have root permission as the test needs to create /etc/kubernetes directory
	// while the permission should be granted to the user.
	isPrivileged := preflight.IsPrivilegedUserCheck{}
	if _, err := isPrivileged.Check(); err != nil {
		return
	}
	testCases := []struct {
		name       string
		dryrun     bool
		patchesDir string
		errPattern string
		cfg        *kubeadmapi.InitConfiguration
	}{
		// Be careful that if the dryrun is set to false and the test is run on a live cluster, the kubelet config file might be overwritten.
		// However, you should be able to find the original config file in /etc/kubernetes/tmp/kubeadm-kubelet-configxxx folder.
		// The test haven't clean up the temporary file created under /etc/kubernetes/tmp/ as that could be accidentally delete other files in
		// that folder as well which might be unexpected.
		{
			name:   "write kubelet config file successfully",
			dryrun: true,
			cfg: &kubeadmapi.InitConfiguration{
				ClusterConfiguration: kubeadmapi.ClusterConfiguration{
					ComponentConfigs: kubeadmapi.ComponentConfigMap{
						componentconfigs.KubeletGroup: &componentConfig{},
					},
				},
			},
		},
		{
			name:       "aggregate errs: no kubelet config file and cannot read config file",
			dryrun:     true,
			errPattern: missingKubeletConfig,
			cfg:        &kubeadmapi.InitConfiguration{},
		},
		{
			name:       "only one err: patch dir does not exist",
			dryrun:     true,
			patchesDir: "Bogus",
			errPattern: "could not list patch files for path \"Bogus\"",
			cfg: &kubeadmapi.InitConfiguration{
				ClusterConfiguration: kubeadmapi.ClusterConfiguration{
					ComponentConfigs: kubeadmapi.ComponentConfigMap{
						componentconfigs.KubeletGroup: &componentConfig{},
					},
				},
			},
		},
	}
	for _, tc := range testCases {
		err := WriteKubeletConfigFiles(tc.cfg, tc.patchesDir, tc.dryrun, os.Stdout)
		if err != nil && tc.errPattern != "" {
			if match, _ := regexp.MatchString(tc.errPattern, err.Error()); !match {
				t.Fatalf("Expected error contains %q, got %v", tc.errPattern, err.Error())
			}
		}
		if err == nil && len(tc.errPattern) != 0 {
			t.Fatalf("WriteKubeletConfigFiles didn't return error expected %s", tc.errPattern)
		}
	}
}