Repository: firecracker-microvm/firecracker
File: src/vmm/src/vstate/vcpu/x86_64.rs (Rust)

Code before:
                    {
                        assert_eq!(msr_data, data);
                    }
                }
            }
        };
    }

    #[test]
    fn test_fix_zero_tsc_deadline_msr_zero() {
        let mut msr_chunks = vec![
            msrs_from_entries!(&[(MSR_TSC_AUX, 1)]),
            msrs_from_entries!(&[(MSR_IA32_TSC_DEADLINE, 0), (MSR_IA32_TSC, 42)]),
        ];

        KvmVcpu::fix_zero_tsc_deadline_msr(&mut msr_chunks);

        // We expect for the MSR_IA32_TSC_DEADLINE to get updated with the MSR_IA32_TSC value, while
        // other MSRs should remain unchanged.
        assert_msrs!(
            msr_chunks,
            &[
                (MSR_TSC_AUX, 1),
                (MSR_IA32_TSC_DEADLINE, 42),
                (MSR_IA32_TSC, 42)
            ]
        );
    }

    #[test]
    fn test_fix_zero_tsc_deadline_msr_non_zero() {
        let mut msr_chunks = vec![msrs_from_entries!(&[
            (MSR_IA32_TSC_DEADLINE, 1),
            (MSR_IA32_TSC, 2)
        ])];

        KvmVcpu::fix_zero_tsc_deadline_msr(&mut msr_chunks);

        // We expect that MSR_IA32_TSC_DEADLINE should remain unchanged, because it is non-zero
        // already.
        assert_msrs!(msr_chunks, &[(MSR_IA32_TSC_DEADLINE, 1), (MSR_IA32_TSC, 2)]);
    }
}


Review comment (suggestion):
Considering `msr_chunks` is a `Vec<Vec<...>>` to do an easier comparison you can flatten the vector into just `Vec<...>` and do a simple loop over 2 vectors.
```Rust
let flat_msr_chunks = msr_chunks.iter().flatten().cloned().collect();
let correct_msrs = [
                (MSR_TSC_AUX, 1),
                (MSR_IA32_TSC_DEADLINE, 42),
                (MSR_IA32_TSC, 42)
            ];
for (a, b) in flat_msr_chunks.iter().zip(correct_msrs.iter()) {
  assert_eq!(a.index, b.index);
  assert_eq!(a.data, b.data);
}
```

Code after:
        // Place both TSC and TSC_DEADLINE MSRs in the same chunk.
        let mut msr_chunks = [msrs_from_entries(&[
            (MSR_IA32_TSC_DEADLINE, 0),
            (MSR_IA32_TSC, 42),
        ])];

        KvmVcpu::fix_zero_tsc_deadline_msr(&mut msr_chunks);

        // We expect for the MSR_IA32_TSC_DEADLINE to get updated with the MSR_IA32_TSC value.
        assert_msrs(
            &msr_chunks,
            &[(MSR_IA32_TSC_DEADLINE, 42), (MSR_IA32_TSC, 42)],
        );
    }

    #[test]
    fn test_fix_zero_tsc_deadline_msr_zero_separate_chunks() {
        // Place both TSC and TSC_DEADLINE MSRs in separate chunks.
        let mut msr_chunks = [
            msrs_from_entries(&[(MSR_IA32_TSC_DEADLINE, 0)]),
            msrs_from_entries(&[(MSR_IA32_TSC, 42)]),
        ];

        KvmVcpu::fix_zero_tsc_deadline_msr(&mut msr_chunks);

        // We expect for the MSR_IA32_TSC_DEADLINE to get updated with the MSR_IA32_TSC value.
        assert_msrs(
            &msr_chunks,
            &[(MSR_IA32_TSC_DEADLINE, 42), (MSR_IA32_TSC, 42)],
        );
    }

    #[test]
    fn test_fix_zero_tsc_deadline_msr_non_zero() {
        let mut msr_chunks = [msrs_from_entries(&[
            (MSR_IA32_TSC_DEADLINE, 1),
            (MSR_IA32_TSC, 2),
        ])];

        KvmVcpu::fix_zero_tsc_deadline_msr(&mut msr_chunks);

        // We expect that MSR_IA32_TSC_DEADLINE should remain unchanged, because it is non-zero
        // already.
        assert_msrs(
            &msr_chunks,
            &[(MSR_IA32_TSC_DEADLINE, 1), (MSR_IA32_TSC, 2)],
        );
    }
}