package nucleus

// import (
// 	"context"
// 	"errors"
// 	"reflect"
// 	"sync"
// 	"testing"
// 	"time"

// 	mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
// 	"code.fbi.h-da.de/danet/gosdn/controller/config"
// 	"github.com/google/uuid"
// 	"github.com/openconfig/ygot/exampleoc"
// 	"github.com/openconfig/ygot/ygot"
// )

// var commitHostname = "commit"
// var rollbackHostname = "rollback"

// var commitDevice = &exampleoc.Device{
// 	System: &exampleoc.System{
// 		Hostname: &commitHostname,
// 	},
// }

// var rollbackDevice = &exampleoc.Device{
// 	System: &exampleoc.System{
// 		Hostname: &rollbackHostname,
// 	},
// }

// func TestChange_CommitRollback(t *testing.T) {
// 	wg := sync.WaitGroup{}
// 	wantErr := false
// 	want := rollbackHostname
// 	callback := make(chan string)
// 	c := &Change{
// 		cuid:          cuid,
// 		duid:          mneid,
// 		timestamp:     time.Now(),
// 		previousState: rollbackDevice,
// 		intendedState: commitDevice,
// 		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
// 			hostname := *first.(*exampleoc.Device).System.Hostname
// 			t.Logf("callback in test %v", t.Name())
// 			switch hostname {
// 			case rollbackHostname:
// 				callback <- rollbackHostname
// 			}
// 			return nil
// 		},
// 	}
// 	stateManagerCtx, stateManagerCancel := context.WithCancel(context.Background())
// 	stateIn, stateOut, errChan := stateManager(stateManagerCtx, c, time.Millisecond*100)
// 	c.stateIn = stateIn
// 	c.stateOut = stateOut
// 	c.errChan = errChan
// 	c.stateManagerCancel = stateManagerCancel
// 	wg.Add(1)
// 	go func() {
// 		defer wg.Done()
// 		time.Sleep(time.Millisecond * 10)
// 		if err := c.Commit(); (err != nil) != wantErr {
// 			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
// 		}
// 		time.Sleep(config.ChangeTimeout)
// 	}()
// 	got := <-callback
// 	if !reflect.DeepEqual(got, want) {
// 		t.Errorf("Commit() = %v, want %v", got, want)
// 	}
// 	wg.Wait()
// 	c.stateManagerCancel()
// }

// func TestChange_CommitRollbackError(t *testing.T) {
// 	wg := sync.WaitGroup{}
// 	wg.Add(1)
// 	wantErr := false
// 	want := errors.New("this is an expected error")
// 	rollbackErrChannel := make(chan error)
// 	c := &Change{
// 		cuid:          cuid,
// 		duid:          mneid,
// 		timestamp:     time.Now(),
// 		previousState: rollbackDevice,
// 		intendedState: commitDevice,
// 		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
// 			hostname := *second.(*exampleoc.Device).System.Hostname
// 			t.Logf("callback in test %v", t.Name())
// 			switch hostname {
// 			case rollbackHostname:
// 				rollbackErrChannel <- errors.New("this is an expected error")
// 			}
// 			return nil
// 		},
// 	}
// 	stateManagerCtx, stateManagerCancel := context.WithCancel(context.Background())
// 	stateIn, stateOut, errChan := stateManager(stateManagerCtx, c, time.Millisecond*100)
// 	c.stateIn = stateIn
// 	c.stateOut = stateOut
// 	c.errChan = errChan
// 	c.stateManagerCancel = stateManagerCancel

// 	go func() {
// 		defer wg.Done()
// 		time.Sleep(time.Millisecond * 10)
// 		if err := c.Commit(); (err != nil) != wantErr {
// 			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
// 		}
// 		time.Sleep(config.ChangeTimeout)
// 	}()
// 	got := <-rollbackErrChannel
// 	if !reflect.DeepEqual(got, want) {
// 		t.Errorf("Commit() = %v, want %v", got, want)
// 	}
// 	wg.Wait()
// 	c.stateManagerCancel()
// }

// func TestChange_CommitError(t *testing.T) {
// 	want := mnepb.ChangeState_CHANGE_STATE_INCONSISTENT
// 	c := &Change{
// 		cuid:          cuid,
// 		duid:          mneid,
// 		timestamp:     time.Now(),
// 		previousState: rollbackDevice,
// 		intendedState: commitDevice,
// 		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
// 			return errors.New("this is an expected error")
// 		},
// 	}
// 	stateManagerCtx, stateManagerCancel := context.WithCancel(context.Background())
// 	stateIn, stateOut, errChan := stateManager(stateManagerCtx, c, time.Millisecond*100)
// 	c.stateIn = stateIn
// 	c.stateOut = stateOut
// 	c.errChan = errChan
// 	c.stateManagerCancel = stateManagerCancel

// 	time.Sleep(time.Millisecond * 10)
// 	if err := c.Commit(); err == nil {
// 		t.Errorf("Commit() expected error, error = %v", err)
// 	}
// 	got := c.State()
// 	if !reflect.DeepEqual(got, want) {
// 		t.Errorf("Commit() = %v, want %v", got, want)
// 	}
// 	c.stateManagerCancel()
// }

// func TestChange_Commit(t *testing.T) {
// 	want := mnepb.ChangeState_CHANGE_STATE_COMMITTED
// 	c := &Change{
// 		cuid:          cuid,
// 		duid:          mneid,
// 		timestamp:     time.Now(),
// 		previousState: rollbackDevice,
// 		intendedState: commitDevice,
// 		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
// 			t.Logf("callback in test %v", t.Name())
// 			return nil
// 		},
// 	}
// 	stateManagerCtx, stateManagerCancel := context.WithCancel(context.Background())
// 	stateIn, stateOut, errChan := stateManager(stateManagerCtx, c, time.Millisecond*100)
// 	c.stateIn = stateIn
// 	c.stateOut = stateOut
// 	c.errChan = errChan
// 	c.stateManagerCancel = stateManagerCancel

// 	if err := c.Commit(); err != nil {
// 		t.Errorf("Commit() error = %v", err)
// 	}
// 	got := c.State()
// 	if !reflect.DeepEqual(got, want) {
// 		t.Errorf("Commit() = %v, want %v", got, want)
// 	}
// 	if err := c.Confirm(); err != nil {
// 		t.Errorf("Confirm() error = %v", err)
// 	}
// }

// func TestChange_Confirm(t *testing.T) {
// 	tests := []struct {
// 		name    string
// 		wantErr bool
// 	}{
// 		{
// 			name:    "committed",
// 			wantErr: false,
// 		},
// 		{
// 			name:    "uncommitted",
// 			wantErr: true,
// 		},
// 	}
// 	for _, tt := range tests {
// 		t.Run(tt.name, func(t *testing.T) {
// 			c := &Change{
// 				previousState: &exampleoc.Device{
// 					System: &exampleoc.System{
// 						Hostname: &rollbackHostname,
// 					},
// 				},
// 				intendedState: &exampleoc.Device{
// 					System: &exampleoc.System{
// 						Hostname: &commitHostname,
// 					},
// 				},
// 				callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
// 					t.Logf("callback in test %v", t.Name())
// 					return nil
// 				},
// 			}
// 			stateManagerCtx, stateManagerCancel := context.WithCancel(context.Background())
// 			stateIn, stateOut, errChan := stateManager(stateManagerCtx, c, time.Millisecond*100)
// 			c.stateIn = stateIn
// 			c.stateOut = stateOut
// 			c.errChan = errChan
// 			c.stateManagerCancel = stateManagerCancel

// 			if tt.name == "committed" {
// 				if err := c.Commit(); err != nil {
// 					t.Errorf("Commit() error = %v, wantErr %v", err, tt.wantErr)
// 				}
// 			}
// 			if err := c.Confirm(); (err != nil) != tt.wantErr {
// 				t.Errorf("Confirm() error = %v, wantErr %v", err, tt.wantErr)
// 			}
// 			c.stateManagerCancel()
// 		})
// 	}
// }

// func TestChange_ID(t *testing.T) {
// 	type fields struct {
// 		cuid uuid.UUID
// 	}
// 	tests := []struct {
// 		name   string
// 		fields fields
// 		want   uuid.UUID
// 	}{
// 		{
// 			name:   "default",
// 			fields: fields{cuid: cuid},
// 			want:   cuid,
// 		},
// 	}
// 	for _, tt := range tests {
// 		t.Run(tt.name, func(t *testing.T) {
// 			c := &Change{
// 				cuid: tt.fields.cuid,
// 			}
// 			if got := c.ID(); !reflect.DeepEqual(got, tt.want) {
// 				t.Errorf("ID() = %v, want %v", got, tt.want)
// 			}
// 		})
// 	}
// }

// func TestChange_State(t *testing.T) {
// 	tests := []struct {
// 		name string
// 		want mnepb.ChangeState
// 	}{
// 		{
// 			name: "pending",
// 			want: mnepb.ChangeState_CHANGE_STATE_PENDING,
// 		},
// 		{
// 			name: "committed",
// 			want: mnepb.ChangeState_CHANGE_STATE_COMMITTED,
// 		},
// 		{
// 			name: "confirmed",
// 			want: mnepb.ChangeState_CHANGE_STATE_CONFIRMED,
// 		},
// 	}
// 	for _, tt := range tests {
// 		t.Run(tt.name, func(t *testing.T) {
// 			testName := t.Name()
// 			callback := func(first ygot.GoStruct, second ygot.GoStruct) error {
// 				t.Logf("callback in test %v", testName)
// 				return nil
// 			}
// 			c := NewChange(mneid, rollbackDevice, commitDevice, callback)
// 			if tt.name != "pending" {
// 				if err := c.Commit(); err != nil {
// 					t.Errorf("Commit() error = %v", err)
// 				}
// 			}
// 			if tt.name == "confirmed" {
// 				if err := c.Confirm(); err != nil {
// 					t.Errorf("Confirm() error = %v", err)
// 				}
// 			}
// 			if got := c.State(); !reflect.DeepEqual(got, tt.want) {
// 				t.Errorf("Change.State() = %v, want %v", got, tt.want)
// 			}
// 			c.stateManagerCancel()
// 		})
// 	}
// }
