diff --git a/cmd/tools/vtest-self.v b/cmd/tools/vtest-self.v index 27f4058af8..7cac8d2930 100644 --- a/cmd/tools/vtest-self.v +++ b/cmd/tools/vtest-self.v @@ -86,8 +86,8 @@ const ( 'do_not_remove', 'cmd/tools/vdoc/html_tag_escape_test.v', /* can't locate local module: markdown */ 'cmd/tools/vdoc/tests/vdoc_file_test.v', /* fails on Windows; order of output is not as expected */ - 'vlib/context/onecontext/onecontext_test.v', 'vlib/context/deadline_test.v' /* sometimes blocks */, + 'vlib/context/onecontext/onecontext_test.v' /* backtrace_symbols is missing. */, 'vlib/db/mysql/mysql_orm_test.v' /* mysql not installed */, 'vlib/db/pg/pg_orm_test.v' /* pg not installed */, ] @@ -246,10 +246,6 @@ const ( ] skip_on_windows = [ 'do_not_remove', - 'vlib/context/cancel_test.v', - 'vlib/context/deadline_test.v', - 'vlib/context/empty_test.v', - 'vlib/context/value_test.v', 'vlib/orm/orm_test.v', 'vlib/v/tests/orm_sub_struct_test.v', 'vlib/v/tests/orm_joined_tables_select_test.v', diff --git a/vlib/context/README.md b/vlib/context/README.md index f3ae603d43..8f5e8f3e81 100644 --- a/vlib/context/README.md +++ b/vlib/context/README.md @@ -62,7 +62,7 @@ fn main() { } mut background := context.background() - mut ctx, cancel := context.with_cancel(mut &background) + mut ctx, cancel := context.with_cancel(mut background) defer { cancel() time.sleep(2 * time.millisecond) // give a small time window, in which the go thread routine has a chance to return @@ -93,7 +93,7 @@ const short_duration = 2 * time.millisecond // a reasonable duration to block in fn main() { dur := time.now().add(short_duration) mut background := context.background() - mut ctx, cancel := context.with_deadline(mut &background, dur) + mut ctx, cancel := context.with_deadline(mut background, dur) defer { // Even though ctx will be expired, it is good practice to call its @@ -131,7 +131,7 @@ fn main() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. mut background := context.background() - mut ctx, cancel := context.with_timeout(mut &background, short_duration) + mut ctx, cancel := context.with_timeout(mut background, short_duration) defer { cancel() eprintln('> defer finishes') diff --git a/vlib/context/cancel_test.v b/vlib/context/cancel_test.v index f1674e7809..e4fea68cf2 100644 --- a/vlib/context/cancel_test.v +++ b/vlib/context/cancel_test.v @@ -32,7 +32,7 @@ fn test_with_cancel() { } mut background := context.background() - mut ctx, cancel := context.with_cancel(mut &background) + mut ctx, cancel := context.with_cancel(mut background) defer { cancel() } diff --git a/vlib/context/context.v b/vlib/context/context.v index ed32b7e1cb..ad33a43ea4 100644 --- a/vlib/context/context.v +++ b/vlib/context/context.v @@ -7,9 +7,6 @@ module context import time const ( - background = EmptyContext(0) - todo = EmptyContext(1) - cancel_context_key = Key('context.CancelContext') // canceled is the error returned by Context.err when the context is canceled. @@ -74,22 +71,6 @@ mut: err() IError } -// background returns an empty Context. It is never canceled, has no -// values, and has no deadline. It is typically used by the main function, -// initialization, and tests, and as the top-level Context for incoming -// requests. -pub fn background() Context { - return context.background -} - -// todo returns an empty Context. Code should use todo when -// it's unclear which Context to use or it is not yet available (because the -// surrounding function has not yet been extended to accept a Context -// parameter). -pub fn todo() Context { - return context.todo -} - fn context_name(ctx Context) string { return typeof(ctx) } diff --git a/vlib/context/deadline_test.v b/vlib/context/deadline_test.v index d983c998bc..fbecf87324 100644 --- a/vlib/context/deadline_test.v +++ b/vlib/context/deadline_test.v @@ -11,7 +11,7 @@ const ( fn test_with_deadline() { dur := time.now().add(short_duration) mut background := context.background() - mut ctx, cancel := context.with_deadline(mut &background, dur) + mut ctx, cancel := context.with_deadline(mut background, dur) defer { // Even though ctx will be expired, it is good practice to call its @@ -35,7 +35,7 @@ fn test_with_timeout() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. mut background := context.background() - mut ctx, cancel := context.with_timeout(mut &background, short_duration) + mut ctx, cancel := context.with_timeout(mut background, short_duration) defer { cancel() } diff --git a/vlib/context/empty.v b/vlib/context/empty.v index e5fe2f7361..738fb56387 100644 --- a/vlib/context/empty.v +++ b/vlib/context/empty.v @@ -6,9 +6,8 @@ module context import time -// An EmptyContext is never canceled, has no values, and has no deadline. It is not -// struct{}, since vars of this type must have distinct addresses. -pub type EmptyContext = int +// An EmptyContext is never canceled, has no values. +pub struct EmptyContext {} pub fn (ctx &EmptyContext) deadline() ?time.Time { return none @@ -16,9 +15,7 @@ pub fn (ctx &EmptyContext) deadline() ?time.Time { pub fn (ctx &EmptyContext) done() chan int { ch := chan int{} - defer { - ch.close() - } + ch.close() return ch } @@ -31,11 +28,42 @@ pub fn (ctx &EmptyContext) value(key Key) ?Any { } pub fn (ctx &EmptyContext) str() string { - if ctx == background { - return 'context.Background' - } - if ctx == todo { - return 'context.TODO' - } return 'unknown empty Context' } + +// A BackgroundContext is never canceled, has no values. +struct BackgroundContext { + EmptyContext +} + +// str returns a string describing the Context. +pub fn (ctx &BackgroundContext) str() string { + return 'context.Background' +} + +// background returns an empty Context. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +pub fn background() Context { + return &BackgroundContext{} +} + +// A TodoContext is never canceled, has no values, and has no deadline. It is +// never used for real work. +struct TodoContext { + EmptyContext +} + +// str returns a string describing the Context. +pub fn (ctx &TodoContext) str() string { + return 'context.TODO' +} + +// todo returns an empty Context. Code should use todo when +// it's unclear which Context to use or it is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). +pub fn todo() Context { + return &TodoContext{} +} diff --git a/vlib/context/onecontext/onecontext.v b/vlib/context/onecontext/onecontext.v index 70f5d0988c..4de9b8278f 100644 --- a/vlib/context/onecontext/onecontext.v +++ b/vlib/context/onecontext/onecontext.v @@ -92,7 +92,7 @@ pub fn (mut octx OneContext) run() { octx.run_multiple_contexts(mut wrapped_ctx) for mut ctx in octx.ctxs { - octx.run_multiple_contexts(mut &ctx) + octx.run_multiple_contexts(mut ctx) } } diff --git a/vlib/context/onecontext/onecontext_test.v b/vlib/context/onecontext/onecontext_test.v index 4bee5fe1c0..5311936c60 100644 --- a/vlib/context/onecontext/onecontext_test.v +++ b/vlib/context/onecontext/onecontext_test.v @@ -5,7 +5,7 @@ import time fn eventually(ch chan int) bool { mut background := context.background() - mut timeout, cancel := context.with_timeout(mut &background, 30 * time.millisecond) + mut timeout, cancel := context.with_timeout(mut background, 30 * time.millisecond) defer { cancel() } @@ -27,32 +27,32 @@ struct Value { val string } -fn test_merge_nomilan() { +fn test_merge_nominal() { mut background := context.background() - foo := &Value{ - val: 'foo' - } + foo := 'foo' mut value_ctx1 := context.with_value(background, 'foo', foo) - mut ctx1, cancel := context.with_cancel(mut &value_ctx1) + mut ctx1, cancel := context.with_cancel(mut value_ctx1) defer { cancel() } - bar := &Value{ - val: 'bar' - } + bar := 'bar' mut value_ctx2 := context.with_value(background, 'bar', bar) - mut ctx2, _ := context.with_cancel(mut &value_ctx2) + mut ctx2, _ := context.with_cancel(mut value_ctx2) mut ctx, cancel2 := merge(ctx1, ctx2) if deadline := ctx.deadline() { - panic('this should never happen') + assert false + } + + val1 := ctx.value('foo') or { + assert false + return } - val1 := ctx.value('foo') or { panic('wrong value access for key `foo`') } match val1 { - Value { + string { assert foo == val1 } else { @@ -60,9 +60,12 @@ fn test_merge_nomilan() { } } - val2 := ctx.value('bar') or { panic('wrong value access for key `bar`') } + val2 := ctx.value('bar') or { + assert false + return + } match val2 { - Value { + string { assert bar == val2 } else { @@ -71,7 +74,7 @@ fn test_merge_nomilan() { } if _ := ctx.value('baz') { - panic('this should never happen') + assert false } assert !eventually(ctx.done()) @@ -79,12 +82,12 @@ fn test_merge_nomilan() { cancel2() assert eventually(ctx.done()) - assert ctx.err() is Error + assert ctx.err().str() == 'canceled context' } fn test_merge_deadline_context_1() { mut background := context.background() - mut ctx1, cancel := context.with_timeout(mut &background, time.second) + mut ctx1, cancel := context.with_timeout(mut background, time.second) defer { cancel() } @@ -94,14 +97,14 @@ fn test_merge_deadline_context_1() { if deadline := ctx.deadline() { assert deadline.unix_time() != 0 } else { - panic('this should never happen') + assert false } } fn test_merge_deadline_context_2() { mut background := context.background() ctx1 := context.background() - mut ctx2, cancel := context.with_timeout(mut &background, time.second) + mut ctx2, cancel := context.with_timeout(mut background, time.second) defer { cancel() } @@ -110,7 +113,7 @@ fn test_merge_deadline_context_2() { if deadline := ctx.deadline() { assert deadline.unix_time() != 0 } else { - panic('this should never happen') + assert false } } @@ -122,7 +125,7 @@ fn test_merge_deadline_context_n() { for i in 0 .. 10 { ctxs << context.background() } - mut ctx_n, _ := context.with_timeout(mut &background, time.second) + mut ctx_n, _ := context.with_timeout(mut background, time.second) ctxs << ctx_n for i in 0 .. 10 { @@ -135,7 +138,7 @@ fn test_merge_deadline_context_n() { assert ctx.err() is none cancel() assert eventually(ctx.done()) - assert ctx.err() is Error + assert ctx.err().str() == 'canceled context' } fn test_merge_deadline_none() { @@ -145,7 +148,7 @@ fn test_merge_deadline_none() { mut ctx, _ := merge(ctx1, ctx2) if _ := ctx.deadline() { - panic('this should never happen') + assert false } } @@ -157,7 +160,7 @@ fn test_merge_cancel_two() { cancel() assert eventually(ctx.done()) - assert ctx.err() is Error + assert ctx.err().str() == 'canceled context' assert ctx.err().str() == 'canceled context' } @@ -170,6 +173,6 @@ fn test_merge_cancel_multiple() { cancel() assert eventually(ctx.done()) - assert ctx.err() is Error + assert ctx.err().str() == 'canceled context' assert ctx.err().str() == 'canceled context' }