system: partial I inherit dispatcher
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 32s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 2m38s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 4m23s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 5m34s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 6m42s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 7m19s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 3m1s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 32s
				
			Test / Sandbox (push) Successful in 2m38s
				
			Test / Hakurei (push) Successful in 4m23s
				
			Test / Sandbox (race detector) (push) Successful in 5m34s
				
			Test / Hpkg (push) Successful in 6m42s
				
			Test / Hakurei (race detector) (push) Successful in 7m19s
				
			Test / Flake checks (push) Successful in 3m1s
				
			This enables I struct methods to be checked. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									c8a0effe90
								
							
						
					
					
						commit
						6265aea73a
					
				| @ -4,7 +4,6 @@ package system | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"log" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| @ -116,14 +115,15 @@ func (sys *I) Commit() error { | ||||
| 	sys.committed = true | ||||
| 
 | ||||
| 	sp := New(sys.ctx, sys.uid) | ||||
| 	sp.syscallDispatcher = sys.syscallDispatcher | ||||
| 	sp.ops = make([]Op, 0, len(sys.ops)) // prevent copies during commits | ||||
| 	defer func() { | ||||
| 		// sp is set to nil when all ops are applied | ||||
| 		if sp != nil { | ||||
| 			// rollback partial commit | ||||
| 			msg.Verbosef("commit faulted after %d ops, rolling back partial commit", len(sp.ops)) | ||||
| 			sys.verbosef("commit faulted after %d ops, rolling back partial commit", len(sp.ops)) | ||||
| 			if err := sp.Revert(nil); err != nil { | ||||
| 				printJoinedError(log.Println, "cannot revert partial commit:", err) | ||||
| 				printJoinedError(sys.println, "cannot revert partial commit:", err) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| @ -1,8 +1,15 @@ | ||||
| package system | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"slices" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"hakurei.app/container/stub" | ||||
| 	"hakurei.app/system/internal/xcb" | ||||
| ) | ||||
| 
 | ||||
| func TestCriteria(t *testing.T) { | ||||
| @ -153,3 +160,143 @@ func TestEqual(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestCommitRevert(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		name string | ||||
| 		f    func(sys *I) | ||||
| 		ec   Enablement | ||||
| 
 | ||||
| 		commit        []stub.Call | ||||
| 		wantErrCommit error | ||||
| 
 | ||||
| 		revert        []stub.Call | ||||
| 		wantErrRevert error | ||||
| 	}{ | ||||
| 		{"apply xhost partial mkdir", func(sys *I) { | ||||
| 			sys. | ||||
| 				Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). | ||||
| 				ChangeHosts("chronos") | ||||
| 		}, 0xff, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 			call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, stub.UniqueError(2)), | ||||
| 			call("verbosef", stub.ExpectArgs{"commit faulted after %d ops, rolling back partial commit", []any{1}}, nil, nil), | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"destroying ephemeral directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, stub.UniqueError(3)), | ||||
| 			call("println", stub.ExpectArgs{[]any{"cannot revert mkdir: unique error 3 injected by the test suite"}}, nil, nil), | ||||
| 		}, &OpError{Op: "xhost", Err: stub.UniqueError(2)}, nil, nil}, | ||||
| 
 | ||||
| 		{"apply xhost", func(sys *I) { | ||||
| 			sys. | ||||
| 				Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). | ||||
| 				ChangeHosts("chronos") | ||||
| 		}, 0xff, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 			call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, stub.UniqueError(2)), | ||||
| 			call("verbosef", stub.ExpectArgs{"commit faulted after %d ops, rolling back partial commit", []any{1}}, nil, nil), | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"destroying ephemeral directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, nil), | ||||
| 		}, &OpError{Op: "xhost", Err: stub.UniqueError(2)}, nil, nil}, | ||||
| 
 | ||||
| 		{"revert multi", func(sys *I) { | ||||
| 			sys. | ||||
| 				Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). | ||||
| 				ChangeHosts("chronos") | ||||
| 		}, 0xff, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 			call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil), | ||||
| 		}, nil, []stub.Call{ | ||||
| 			call("verbosef", stub.ExpectArgs{"deleting entry %s from X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeDelete), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, stub.UniqueError(1)), | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"destroying ephemeral directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, stub.UniqueError(0)), | ||||
| 		}, errors.Join( | ||||
| 			&OpError{Op: "xhost", Err: stub.UniqueError(1), Revert: true}, | ||||
| 			&OpError{Op: "mkdir", Err: stub.UniqueError(0), Revert: true})}, | ||||
| 
 | ||||
| 		{"success", func(sys *I) { | ||||
| 			sys. | ||||
| 				Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). | ||||
| 				ChangeHosts("chronos") | ||||
| 		}, 0xff, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 			call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil), | ||||
| 		}, nil, []stub.Call{ | ||||
| 			call("verbosef", stub.ExpectArgs{"deleting entry %s from X11", []any{xhostOp("chronos")}}, nil, nil), | ||||
| 			call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeDelete), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil), | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"destroying ephemeral directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, nil), | ||||
| 		}, nil}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			var ec *Criteria | ||||
| 			if tc.ec != 0xff { | ||||
| 				ec = (*Criteria)(&tc.ec) | ||||
| 			} | ||||
| 
 | ||||
| 			sys, s := InternalNew(t, stub.Expect{Calls: slices.Concat(tc.commit, []stub.Call{{Name: stub.CallSeparator}}, tc.revert)}, 0xbad) | ||||
| 			defer stub.HandleExit(t) | ||||
| 			tc.f(sys) | ||||
| 			errCommit := sys.Commit() | ||||
| 			s.Expects(stub.CallSeparator) | ||||
| 			if !reflect.DeepEqual(errCommit, tc.wantErrCommit) { | ||||
| 				t.Errorf("Commit: error = %v, want %v", errCommit, tc.wantErrCommit) | ||||
| 			} | ||||
| 			if errCommit != nil { | ||||
| 				goto out | ||||
| 			} | ||||
| 
 | ||||
| 			if err := sys.Revert(ec); !reflect.DeepEqual(err, tc.wantErrRevert) { | ||||
| 				t.Errorf("Revert: error = %v, want %v", err, tc.wantErrRevert) | ||||
| 			} | ||||
| 
 | ||||
| 		out: | ||||
| 			s.VisitIncomplete(func(s *stub.Stub[syscallDispatcher]) { | ||||
| 				count := s.Pos() - 1 // separator | ||||
| 				if count < len(tc.commit) { | ||||
| 					t.Errorf("Commit: %d calls, want %d", count, len(tc.commit)) | ||||
| 				} else { | ||||
| 					t.Errorf("Revert: %d calls, want %d", count-len(tc.commit), len(tc.revert)) | ||||
| 				} | ||||
| 			}) | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	t.Run("panic", func(t *testing.T) { | ||||
| 		t.Run("committed", func(t *testing.T) { | ||||
| 			defer func() { | ||||
| 				want := "attempting to commit twice" | ||||
| 				if r := recover(); r != want { | ||||
| 					t.Errorf("Commit: panic = %v, want %v", r, want) | ||||
| 				} | ||||
| 			}() | ||||
| 			_ = (&I{committed: true}).Commit() | ||||
| 		}) | ||||
| 
 | ||||
| 		t.Run("reverted", func(t *testing.T) { | ||||
| 			defer func() { | ||||
| 				want := "attempting to revert twice" | ||||
| 				if r := recover(); r != want { | ||||
| 					t.Errorf("Revert: panic = %v, want %v", r, want) | ||||
| 				} | ||||
| 			}() | ||||
| 			_ = (&I{reverted: true}).Revert(nil) | ||||
| 		}) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func TestNop(t *testing.T) { | ||||
| 	// these do nothing | ||||
| 	new(noCopy).Unlock() | ||||
| 	new(noCopy).Lock() | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user