system/mkdir: use syscall dispatcher
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 32s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 2m7s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 3m8s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 3m55s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 4m29s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 5m4s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 1m25s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 32s
				
			Test / Sandbox (push) Successful in 2m7s
				
			Test / Hakurei (push) Successful in 3m8s
				
			Test / Hpkg (push) Successful in 3m55s
				
			Test / Sandbox (race detector) (push) Successful in 4m29s
				
			Test / Hakurei (race detector) (push) Successful in 5m4s
				
			Test / Flake checks (push) Successful in 1m25s
				
			This enables mkdir op methods to be instrumented. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									6cc2b406a4
								
							
						
					
					
						commit
						323d132c40
					
				| @ -15,6 +15,10 @@ type syscallDispatcher interface { | ||||
| 	// just synchronising access is not enough, as this is for test instrumentation. | ||||
| 	new(f func(k syscallDispatcher)) | ||||
| 
 | ||||
| 	// mkdir provides os.Mkdir. | ||||
| 	mkdir(name string, perm os.FileMode) error | ||||
| 	// chmod provides os.Chmod. | ||||
| 	chmod(name string, mode os.FileMode) error | ||||
| 	// link provides os.Link. | ||||
| 	link(oldname, newname string) error | ||||
| 	// remove provides os.Remove. | ||||
| @ -44,6 +48,8 @@ type direct struct{} | ||||
| 
 | ||||
| func (k direct) new(f func(k syscallDispatcher)) { go f(k) } | ||||
| 
 | ||||
| func (k direct) mkdir(name string, perm os.FileMode) error { return os.Mkdir(name, perm) } | ||||
| func (k direct) chmod(name string, mode os.FileMode) error { return os.Chmod(name, mode) } | ||||
| func (k direct) link(oldname, newname string) error        { return os.Link(oldname, newname) } | ||||
| func (k direct) remove(name string) error                  { return os.Remove(name) } | ||||
| 
 | ||||
|  | ||||
| @ -192,6 +192,20 @@ type kstub struct{ *stub.Stub[syscallDispatcher] } | ||||
| 
 | ||||
| func (k *kstub) new(f func(k syscallDispatcher)) { k.Helper(); k.New(f) } | ||||
| 
 | ||||
| func (k *kstub) mkdir(name string, perm os.FileMode) error { | ||||
| 	k.Helper() | ||||
| 	return k.Expects("mkdir").Error( | ||||
| 		stub.CheckArg(k.Stub, "name", name, 0), | ||||
| 		stub.CheckArg(k.Stub, "perm", perm, 1)) | ||||
| } | ||||
| 
 | ||||
| func (k *kstub) chmod(name string, mode os.FileMode) error { | ||||
| 	k.Helper() | ||||
| 	return k.Expects("chmod").Error( | ||||
| 		stub.CheckArg(k.Stub, "name", name, 0), | ||||
| 		stub.CheckArg(k.Stub, "mode", mode, 1)) | ||||
| } | ||||
| 
 | ||||
| func (k *kstub) link(oldname, newname string) error { | ||||
| 	k.Helper() | ||||
| 	return k.Expects("link").Error( | ||||
|  | ||||
| @ -28,32 +28,31 @@ type mkdirOp struct { | ||||
| 
 | ||||
| func (m *mkdirOp) Type() Enablement { return m.et } | ||||
| 
 | ||||
| func (m *mkdirOp) apply(*I) error { | ||||
| 	msg.Verbose("ensuring directory", m) | ||||
| func (m *mkdirOp) apply(sys *I) error { | ||||
| 	sys.verbose("ensuring directory", m) | ||||
| 
 | ||||
| 	// create directory | ||||
| 	if err := os.Mkdir(m.path, m.perm); err != nil { | ||||
| 	if err := sys.mkdir(m.path, m.perm); err != nil { | ||||
| 		if !errors.Is(err, os.ErrExist) { | ||||
| 			return newOpError("mkdir", err, false) | ||||
| 		} | ||||
| 		// directory exists, ensure mode | ||||
| 		return newOpError("mkdir", os.Chmod(m.path, m.perm), false) | ||||
| 		return newOpError("mkdir", sys.chmod(m.path, m.perm), false) | ||||
| 	} else { | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (m *mkdirOp) revert(_ *I, ec *Criteria) error { | ||||
| func (m *mkdirOp) revert(sys *I, ec *Criteria) error { | ||||
| 	if !m.ephemeral { | ||||
| 		// skip non-ephemeral dir and do not log anything | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if ec.hasType(m.Type()) { | ||||
| 		msg.Verbose("destroying ephemeral directory", m) | ||||
| 		return newOpError("mkdir", os.Remove(m.path), true) | ||||
| 		sys.verbose("destroying ephemeral directory", m) | ||||
| 		return newOpError("mkdir", sys.remove(m.path), true) | ||||
| 	} else { | ||||
| 		msg.Verbose("skipping ephemeral directory", m) | ||||
| 		sys.verbose("skipping ephemeral directory", m) | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -4,72 +4,108 @@ import ( | ||||
| 	"os" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"hakurei.app/container" | ||||
| 	"hakurei.app/container/stub" | ||||
| ) | ||||
| 
 | ||||
| func TestEnsure(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		name string | ||||
| 		perm os.FileMode | ||||
| 	}{ | ||||
| 		{"/tmp/hakurei.1971", 0701}, | ||||
| 		{"/tmp/hakurei.1971/tmpdir", 0700}, | ||||
| 		{"/tmp/hakurei.1971/tmpdir/150", 0700}, | ||||
| 		{"/run/user/1971/hakurei", 0700}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run(tc.name+"_"+tc.perm.String(), func(t *testing.T) { | ||||
| 			sys := New(t.Context(), 150) | ||||
| 			sys.Ensure(tc.name, tc.perm) | ||||
| 			(&tcOp{User, tc.name}).test(t, sys.ops, []Op{&mkdirOp{User, tc.name, tc.perm, false}}, "Ensure") | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| func TestMkdirOp(t *testing.T) { | ||||
| 	checkOpBehaviour(t, []opBehaviourTestCase{ | ||||
| 		{"mkdir", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(2)), | ||||
| 		}, &OpError{Op: "mkdir", Err: stub.UniqueError(2)}, nil, nil}, | ||||
| 
 | ||||
| func TestEphemeral(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		perm os.FileMode | ||||
| 		tcOp | ||||
| 	}{ | ||||
| 		{0700, tcOp{Process, "/run/user/1971/hakurei/ec07546a772a07cde87389afc84ffd13"}}, | ||||
| 		{0701, tcOp{Process, "/tmp/hakurei.1971/ec07546a772a07cde87389afc84ffd13"}}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run(tc.path+"_"+tc.perm.String()+"_"+TypeString(tc.et), func(t *testing.T) { | ||||
| 			sys := New(t.Context(), 150) | ||||
| 			sys.Ephemeral(tc.et, tc.path, tc.perm) | ||||
| 			tc.test(t, sys.ops, []Op{&mkdirOp{tc.et, tc.path, tc.perm, true}}, "Ephemeral") | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 		{"chmod", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist), | ||||
| 			call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(1)), | ||||
| 		}, &OpError{Op: "mkdir", Err: stub.UniqueError(1)}, nil, nil}, | ||||
| 
 | ||||
| func TestMkdirString(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		want      string | ||||
| 		ephemeral bool | ||||
| 		et        Enablement | ||||
| 	}{ | ||||
| 		{"ensure", false, User}, | ||||
| 		{"ensure", false, Process}, | ||||
| 		{"ensure", false, EWayland}, | ||||
| 		{"remove", 0xdeadbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []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), | ||||
| 		}, nil, []stub.Call{ | ||||
| 			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)), | ||||
| 		}, &OpError{Op: "mkdir", Err: stub.UniqueError(0), Revert: true}}, | ||||
| 
 | ||||
| 		{"wayland", true, EWayland}, | ||||
| 		{"x11", true, EX11}, | ||||
| 		{"dbus", true, EDBus}, | ||||
| 		{"pulseaudio", true, EPulse}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		t.Run(tc.want, func(t *testing.T) { | ||||
| 			m := &mkdirOp{ | ||||
| 				et:        tc.et, | ||||
| 				path:      container.Nonexistent, | ||||
| 				perm:      0701, | ||||
| 				ephemeral: tc.ephemeral, | ||||
| 			} | ||||
| 			want := "mode: " + os.FileMode(0701).String() + " type: " + tc.want + ` path: "/proc/nonexistent"` | ||||
| 			if got := m.String(); got != want { | ||||
| 				t.Errorf("String() = %v, want %v", got, want) | ||||
| 			} | ||||
| 		{"success exist chmod", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist), | ||||
| 			call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 		}, nil, nil, nil}, | ||||
| 
 | ||||
| 		{"success ensure", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 		}, nil, nil, nil}, | ||||
| 
 | ||||
| 		{"success skip", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 			call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), | ||||
| 		}, nil, []stub.Call{ | ||||
| 			call("verbose", stub.ExpectArgs{[]any{"skipping ephemeral directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), | ||||
| 		}, nil}, | ||||
| 
 | ||||
| 		{"success", 0xdeadbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []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), | ||||
| 		}, nil, []stub.Call{ | ||||
| 			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}, | ||||
| 	}) | ||||
| 
 | ||||
| 	checkOpsBuilder(t, "EnsureEphemeral", []opsBuilderTestCase{ | ||||
| 		{"ensure", 0xcafebabe, func(_ *testing.T, sys *I) { | ||||
| 			sys.Ensure("/tmp/hakurei.0", 0700) | ||||
| 		}, []Op{ | ||||
| 			&mkdirOp{User, "/tmp/hakurei.0", 0700, false}, | ||||
| 		}, stub.Expect{}}, | ||||
| 
 | ||||
| 		{"ephemeral", 0xcafebabe, func(_ *testing.T, sys *I) { | ||||
| 			sys.Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711) | ||||
| 		}, []Op{ | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, | ||||
| 		}, stub.Expect{}}, | ||||
| 	}) | ||||
| 
 | ||||
| 	checkOpIs(t, []opIsTestCase{ | ||||
| 		{"nil", (*mkdirOp)(nil), (*mkdirOp)(nil), false}, | ||||
| 		{"zero", new(mkdirOp), new(mkdirOp), true}, | ||||
| 
 | ||||
| 		{"ephemeral differs", | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, false}, | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"perm differs", | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0701, true}, | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"path differs", | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.1/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"et differs", | ||||
| 			&mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			false}, | ||||
| 
 | ||||
| 		{"equals", | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			true}, | ||||
| 	}) | ||||
| 
 | ||||
| 	checkOpMeta(t, []opMetaTestCase{ | ||||
| 		{"ensure", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, false}, | ||||
| 			User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", | ||||
| 			`mode: -rwx------ type: ensure path: "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"`}, | ||||
| 
 | ||||
| 		{"ephemeral", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0700, true}, | ||||
| 			User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", | ||||
| 			`mode: -rwx------ type: user path: "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"`}, | ||||
| 	}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user