Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

builtin: fix m.clear() having different observable behavior to m = {}, after multiple iterations of setting keys and clearing (fix #22145) #22146

Merged

Conversation

spytheman
Copy link
Member

@spytheman spytheman commented Sep 1, 2024

Fix #22145 .

…}`, after multiple iterations of setting keys and clearing (fix vlang#22145)
@spytheman
Copy link
Member Author

I've left this running locally:

import rand

const t = get_random_numbers()

fn get_random_numbers() []int {
	mut res := []int{}
	for i in 0..100 {
		res << rand.intn(1000) or { 0 }
	}
	return res
}

fn test_multiple_iterations_of_calling_clear_should_be_always_equivalent_to_assigning_a_new_map() {
	println('array t len: ${t.len}, t: ${t}')
	mut clr := map[int]int{}
	for i in 0 .. 0xFFFF {
		mut new := map[int]int{}
		clr.clear()
		for e in t {
			new[e] = e
			clr[e] = e
			assert new.len == clr.len // , 'mismatch found after setting element: $e, on iteration ${i}'
		}
		if i == 0 {
			dump(new.len)
			dump(new)
		}
		if i & 0x1FFF == 0 {
			println('index ${i}')
			// println('>> map     new: ${new.len} | ${new.keys().sorted()}')
			// println('>> map cleared: ${clr.len} | ${clr.keys().sorted()}')
		}
		assert new == clr // , 'mismatch found for iteration: ${i}'
	}
}

with this runner VFLAGS='-cc clang-18 -prod' ./run_randomised_test.sh:

#!/bin/bash

set -xe

while true; do
	date;
	v crun randomised_test.v ;
	sleep 0.1;
done

So far, it has not found other problems.

@spytheman spytheman merged commit 33f74cf into vlang:master Sep 1, 2024
75 checks passed
@spytheman
Copy link
Member Author

The randomized test, found a counter example, that boils down to:

const t = [928, 897, 165, 563, 52, 619, 525, 414, 555, 254, 788, 8, 534, 0]

fn test_multiple_iterations_of_calling_clear_should_be_always_equivalent_to_assigning_a_new_map() {
    println('array t len: ${t.len}, t: ${t}')
    mut clr := map[int]int{}
    for i in 0 .. 0xFFFF {
        mut new := map[int]int{}
        clr.clear()
        for e in t {
            new[e] = e
            clr[e] = e
        }
        assert new == clr, 'mismatch found for iteration: ${i}'
    }
}

In it, const t = [928, 897, 165, 563, 52, 619, 525, 414, 555, 254, 788, 8, 534, 0] is interesting, since removing one of the elements, makes it pass. Changing some of the keys, like 165 to 65 or 0 to 1,2,3,4,5 also makes it pass, but other values can be changed and it still fails, for example 928 can become 28 or 897 -> 97 etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

After calling clear() on a map several times, duplicate keys are allowed
1 participant