system: improve tests of the I struct
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 35s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 2m5s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 3m20s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 3m57s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 4m41s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 5m25s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 1m39s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 35s
				
			Test / Sandbox (push) Successful in 2m5s
				
			Test / Hakurei (push) Successful in 3m20s
				
			Test / Hpkg (push) Successful in 3m57s
				
			Test / Sandbox (race detector) (push) Successful in 4m41s
				
			Test / Hakurei (race detector) (push) Successful in 5m25s
				
			Test / Flake checks (push) Successful in 1m39s
				
			This cleans up for the test overhaul of this package. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									6f719bc3c1
								
							
						
					
					
						commit
						024d2ff782
					
				| @ -36,7 +36,7 @@ func (a *ACLUpdateOp) apply(sys *I) error { | ||||
| } | ||||
| 
 | ||||
| func (a *ACLUpdateOp) revert(sys *I, ec *Criteria) error { | ||||
| 	if ec.hasType(a) { | ||||
| 	if ec.hasType(a.Type()) { | ||||
| 		msg.Verbose("stripping ACL", a) | ||||
| 		err := acl.Update(a.path, sys.uid) | ||||
| 		if errors.Is(err, os.ErrNotExist) { | ||||
|  | ||||
| @ -28,7 +28,7 @@ func (l *HardlinkOp) apply(*I) error { | ||||
| } | ||||
| 
 | ||||
| func (l *HardlinkOp) revert(_ *I, ec *Criteria) error { | ||||
| 	if ec.hasType(l) { | ||||
| 	if ec.hasType(l.Type()) { | ||||
| 		msg.Verbosef("removing hard link %q", l.dst) | ||||
| 		return newOpError("hardlink", os.Remove(l.dst), true) | ||||
| 	} else { | ||||
|  | ||||
| @ -50,7 +50,7 @@ func (m *MkdirOp) revert(_ *I, ec *Criteria) error { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if ec.hasType(m) { | ||||
| 	if ec.hasType(m.Type()) { | ||||
| 		msg.Verbose("destroying ephemeral directory", m) | ||||
| 		return newOpError("mkdir", os.Remove(m.path), true) | ||||
| 	} else { | ||||
|  | ||||
| @ -209,18 +209,22 @@ func (ptc tcOp) test(t *testing.T, gotOps []Op, wantOps []Op, fn string) { | ||||
| 		t.Run("criteria", func(t *testing.T) { | ||||
| 			testCases := []struct { | ||||
| 				name string | ||||
| 				ec   *Criteria | ||||
| 				ec   Enablement | ||||
| 				want bool | ||||
| 			}{ | ||||
| 				{"nil", nil, ptc.et != User}, | ||||
| 				{"self", newCriteria(ptc.et), true}, | ||||
| 				{"all", newCriteria(EWayland | EX11 | EDBus | EPulse | User | Process), true}, | ||||
| 				{"enablements", newCriteria(EWayland | EX11 | EDBus | EPulse), ptc.et != User && ptc.et != Process}, | ||||
| 				{"nil", 0xff, ptc.et != User}, | ||||
| 				{"self", ptc.et, true}, | ||||
| 				{"all", EWayland | EX11 | EDBus | EPulse | User | Process, true}, | ||||
| 				{"enablements", EWayland | EX11 | EDBus | EPulse, ptc.et != User && ptc.et != Process}, | ||||
| 			} | ||||
| 
 | ||||
| 			for _, tc := range testCases { | ||||
| 				t.Run(tc.name, func(t *testing.T) { | ||||
| 					if got := tc.ec.hasType(o); got != tc.want { | ||||
| 					var criteria *Criteria | ||||
| 					if tc.ec != 0xff { | ||||
| 						criteria = (*Criteria)(&tc.ec) | ||||
| 					} | ||||
| 					if got := criteria.hasType(o.Type()); got != tc.want { | ||||
| 						t.Errorf("hasType: got %v, want %v", | ||||
| 							got, tc.want) | ||||
| 					} | ||||
| @ -229,5 +233,3 @@ func (ptc tcOp) test(t *testing.T, gotOps []Op, wantOps []Op, fn string) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func newCriteria(e Enablement) *Criteria { return (*Criteria)(&e) } | ||||
|  | ||||
| @ -20,13 +20,13 @@ const ( | ||||
| // Criteria specifies types of Op to revert. | ||||
| type Criteria Enablement | ||||
| 
 | ||||
| func (ec *Criteria) hasType(o Op) bool { | ||||
| func (ec *Criteria) hasType(t Enablement) bool { | ||||
| 	// nil criteria: revert everything except User | ||||
| 	if ec == nil { | ||||
| 		return o.Type() != User | ||||
| 		return t != User | ||||
| 	} | ||||
| 
 | ||||
| 	return Enablement(*ec)&o.Type() != 0 | ||||
| 	return Enablement(*ec)&t != 0 | ||||
| } | ||||
| 
 | ||||
| // Op is a reversible system operation. | ||||
| @ -92,7 +92,7 @@ func (sys *I) UID() int { return sys.uid } | ||||
| 
 | ||||
| // Equal returns whether all [Op] instances held by sys matches that of target. | ||||
| func (sys *I) Equal(target *I) bool { | ||||
| 	if target == nil || sys.uid != target.uid || len(sys.ops) != len(target.ops) { | ||||
| 	if sys == nil || target == nil || sys.uid != target.uid || len(sys.ops) != len(target.ops) { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| @ -149,7 +149,6 @@ func (sys *I) Revert(ec *Criteria) error { | ||||
| 
 | ||||
| 	// collect errors | ||||
| 	errs := make([]error, len(sys.ops)) | ||||
| 
 | ||||
| 	for i := range sys.ops { | ||||
| 		errs[i] = sys.ops[len(sys.ops)-i-1].revert(sys, ec) | ||||
| 	} | ||||
|  | ||||
| @ -1,28 +1,37 @@ | ||||
| package system_test | ||||
| 
 | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 	_ "unsafe" | ||||
| 
 | ||||
| 	"hakurei.app/system" | ||||
| ) | ||||
| 
 | ||||
| func TestNew(t *testing.T) { | ||||
| //go:linkname criteriaHasType hakurei.app/system.(*Criteria).hasType | ||||
| func criteriaHasType(_ *system.Criteria, _ system.Enablement) bool | ||||
| 
 | ||||
| func TestCriteria(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		uid int | ||||
| 		name  string | ||||
| 		ec, t system.Enablement | ||||
| 		want  bool | ||||
| 	}{ | ||||
| 		{150}, | ||||
| 		{149}, | ||||
| 		{148}, | ||||
| 		{147}, | ||||
| 		{"nil", 0xff, system.EWayland, true}, | ||||
| 		{"nil user", 0xff, system.User, false}, | ||||
| 		{"all", system.EWayland | system.EX11 | system.EDBus | system.EPulse | system.User | system.Process, system.Process, true}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run("sys initialised with uid "+strconv.Itoa(tc.uid), func(t *testing.T) { | ||||
| 			if got := system.New(t.Context(), tc.uid); got.UID() != tc.uid { | ||||
| 				t.Errorf("New(%d) uid = %d, want %d", | ||||
| 					tc.uid, | ||||
| 					got.UID(), tc.uid) | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			var criteria *system.Criteria | ||||
| 			if tc.ec != 0xff { | ||||
| 				criteria = (*system.Criteria)(&tc.ec) | ||||
| 			} | ||||
| 			if got := criteriaHasType(criteria, tc.t); got != tc.want { | ||||
| 				t.Errorf("hasType: got %v, want %v", | ||||
| 					got, tc.want) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| @ -45,86 +54,108 @@ func TestTypeString(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run("label type string "+tc.want, func(t *testing.T) { | ||||
| 		t.Run("label type string "+strconv.Itoa(int(tc.e)), func(t *testing.T) { | ||||
| 			if got := system.TypeString(tc.e); got != tc.want { | ||||
| 				t.Errorf("TypeString: %q, want %q", | ||||
| 					got, tc.want) | ||||
| 				t.Errorf("TypeString: %q, want %q", got, tc.want) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestI_Equal(t *testing.T) { | ||||
| func TestNew(t *testing.T) { | ||||
| 	t.Run("panic", func(t *testing.T) { | ||||
| 		t.Run("ctx", func(t *testing.T) { | ||||
| 			defer func() { | ||||
| 				want := "invalid call to New" | ||||
| 				if r := recover(); r != want { | ||||
| 					t.Errorf("recover: %v, want %v", r, want) | ||||
| 				} | ||||
| 			}() | ||||
| 			system.New(nil, 0) | ||||
| 		}) | ||||
| 
 | ||||
| 		t.Run("uid", func(t *testing.T) { | ||||
| 			defer func() { | ||||
| 				want := "invalid call to New" | ||||
| 				if r := recover(); r != want { | ||||
| 					t.Errorf("recover: %v, want %v", r, want) | ||||
| 				} | ||||
| 			}() | ||||
| 			system.New(t.Context(), -1) | ||||
| 		}) | ||||
| 	}) | ||||
| 
 | ||||
| 	sys := system.New(t.Context(), 0xdeadbeef) | ||||
| 	if got := reflect.ValueOf(sys).Elem().FieldByName("ctx"); got.IsNil() { | ||||
| 		t.Errorf("New: ctx = %#v", got) | ||||
| 	} | ||||
| 	if got := sys.UID(); got != 0xdeadbeef { | ||||
| 		t.Errorf("UID: %d", got) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestEqual(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		name string | ||||
| 		sys  *system.I | ||||
| 		v    *system.I | ||||
| 		want bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"simple UID", | ||||
| 		{"simple UID", | ||||
| 			system.New(t.Context(), 150), | ||||
| 			system.New(t.Context(), 150), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"simple UID differ", | ||||
| 			true}, | ||||
| 
 | ||||
| 		{"simple UID differ", | ||||
| 			system.New(t.Context(), 150), | ||||
| 			system.New(t.Context(), 151), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"simple UID nil", | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"simple UID nil", | ||||
| 			system.New(t.Context(), 150), | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"op length mismatch", | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"op length mismatch", | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"), | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0755), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"op value mismatch", | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"op value mismatch", | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0644), | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0755), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"op type mismatch", | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"op type mismatch", | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 0, 256), | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0755), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"op equals", | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"op equals", | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0755), | ||||
| 			system.New(t.Context(), 150). | ||||
| 				ChangeHosts("chronos"). | ||||
| 				Ensure("/run", 0755), | ||||
| 			true, | ||||
| 		}, | ||||
| 			true}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			if tc.sys.Equal(tc.v) != tc.want { | ||||
| 				t.Errorf("Equal: got %v; want %v", | ||||
| 					!tc.want, tc.want) | ||||
| 				t.Errorf("Equal: %v, want %v", !tc.want, tc.want) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| @ -59,7 +59,7 @@ func (w *WaylandOp) apply(sys *I) error { | ||||
| } | ||||
| 
 | ||||
| func (w *WaylandOp) revert(_ *I, ec *Criteria) error { | ||||
| 	if ec.hasType(w) { | ||||
| 	if ec.hasType(w.Type()) { | ||||
| 		msg.Verbosef("removing wayland socket on %q", w.dst) | ||||
| 		if err := os.Remove(w.dst); err != nil && !errors.Is(err, os.ErrNotExist) { | ||||
| 			return newOpError("wayland", err, true) | ||||
|  | ||||
| @ -22,7 +22,7 @@ func (x XHostOp) apply(*I) error { | ||||
| } | ||||
| 
 | ||||
| func (x XHostOp) revert(_ *I, ec *Criteria) error { | ||||
| 	if ec.hasType(x) { | ||||
| 	if ec.hasType(x.Type()) { | ||||
| 		msg.Verbosef("deleting entry %s from X11", x) | ||||
| 		return newOpError("xhost", | ||||
| 			xcb.ChangeHosts(xcb.HostModeDelete, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), false) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user