1use crate::stdlib::collections::HashSet;
2use core::cmp::max;
3use core::fmt;
4
5use crate::vm::runners::cairo_pie::CairoPieMemory;
6use crate::Felt252;
7use num_traits::Zero;
8
9use crate::stdlib::prelude::*;
10use crate::stdlib::{any::Any, collections::HashMap};
11use crate::vm::runners::cairo_runner::CairoArg;
12
13use crate::{
14 types::relocatable::{MaybeRelocatable, Relocatable},
15 vm::{
16 errors::memory_errors::MemoryError, errors::vm_errors::VirtualMachineError,
17 vm_memory::memory::Memory,
18 },
19};
20
21use super::memory::MemoryCell;
22
23pub struct MemorySegmentManager {
24 pub segment_sizes: HashMap<usize, usize>,
25 pub segment_used_sizes: Option<Vec<usize>>,
26 pub memory: Memory,
27 pub public_memory_offsets: HashMap<usize, Vec<(usize, usize)>>,
30 zero_segment_index: usize,
33 zero_segment_size: usize,
35}
36
37impl MemorySegmentManager {
38 pub fn num_segments(&self) -> usize {
40 self.memory.data.len()
41 }
42
43 pub fn num_temp_segments(&self) -> usize {
45 self.memory.temp_data.len()
46 }
47
48 pub fn add(&mut self) -> Relocatable {
50 self.memory.data.push(Vec::new());
51 Relocatable {
52 segment_index: (self.memory.data.len() - 1) as isize,
53 offset: 0,
54 }
55 }
56
57 pub fn add_temporary_segment(&mut self) -> Relocatable {
59 self.memory.temp_data.push(Vec::new());
60 Relocatable {
61 segment_index: -((self.memory.temp_data.len()) as isize),
63 offset: 0,
64 }
65 }
66
67 pub fn load_data(
69 &mut self,
70 ptr: Relocatable,
71 data: &[MaybeRelocatable],
72 ) -> Result<Relocatable, MemoryError> {
73 for (num, value) in data.iter().enumerate().rev() {
76 self.memory.insert((ptr + num)?, value)?;
77 }
78 (ptr + data.len()).map_err(MemoryError::Math)
79 }
80
81 pub fn new() -> MemorySegmentManager {
82 MemorySegmentManager {
83 segment_sizes: HashMap::new(),
84 segment_used_sizes: None,
85 public_memory_offsets: HashMap::new(),
86 memory: Memory::new(),
87 zero_segment_index: 0,
88 zero_segment_size: 0,
89 }
90 }
91
92 pub fn compute_effective_sizes(&mut self) -> &Vec<usize> {
94 self.segment_used_sizes
95 .get_or_insert_with(|| self.memory.data.iter().map(Vec::len).collect())
96 }
97
98 pub fn get_segment_used_size(&self, index: usize) -> Option<usize> {
101 self.segment_used_sizes.as_ref()?.get(index).copied()
102 }
103
104 pub fn get_segment_size(&self, index: usize) -> Option<usize> {
105 self.segment_sizes
106 .get(&index)
107 .cloned()
108 .or_else(|| self.get_segment_used_size(index))
109 }
110
111 pub fn relocate_segments(&self) -> Result<Vec<usize>, MemoryError> {
113 let first_addr = 1;
114 let mut relocation_table = vec![first_addr];
115 match &self.segment_used_sizes {
116 Some(segment_used_sizes) => {
117 for (i, _size) in segment_used_sizes.iter().enumerate() {
118 let segment_size = self
119 .get_segment_size(i)
120 .ok_or(MemoryError::MissingSegmentUsedSizes)?;
121
122 relocation_table.push(relocation_table[i] + segment_size);
123 }
124 }
125 None => return Err(MemoryError::MissingSegmentUsedSizes),
126 }
127 relocation_table.pop();
129 Ok(relocation_table)
130 }
131
132 pub fn gen_arg(&mut self, arg: &dyn Any) -> Result<MaybeRelocatable, MemoryError> {
133 if let Some(value) = arg.downcast_ref::<MaybeRelocatable>() {
134 Ok(value.clone())
135 } else if let Some(value) = arg.downcast_ref::<Vec<MaybeRelocatable>>() {
136 let base = self.add();
137 self.write_arg(base, value)?;
138 Ok(base.into())
139 } else if let Some(value) = arg.downcast_ref::<Vec<Relocatable>>() {
140 let base = self.add();
141 self.write_arg(base, value)?;
142 Ok(base.into())
143 } else {
144 Err(MemoryError::GenArgInvalidType)
145 }
146 }
147
148 pub fn gen_cairo_arg(
149 &mut self,
150 arg: &CairoArg,
151 ) -> Result<MaybeRelocatable, VirtualMachineError> {
152 match arg {
153 CairoArg::Single(value) => Ok(value.clone()),
154 CairoArg::Array(values) => {
155 let base = self.add();
156 self.load_data(base, values)?;
157 Ok(base.into())
158 }
159 CairoArg::Composed(cairo_args) => {
160 let args = cairo_args
161 .iter()
162 .map(|cairo_arg| self.gen_cairo_arg(cairo_arg))
163 .collect::<Result<Vec<MaybeRelocatable>, VirtualMachineError>>()?;
164 let base = self.add();
165 self.load_data(base, &args)?;
166 Ok(base.into())
167 }
168 }
169 }
170
171 pub fn write_arg(
172 &mut self,
173 ptr: Relocatable,
174 arg: &dyn Any,
175 ) -> Result<MaybeRelocatable, MemoryError> {
176 if let Some(vector) = arg.downcast_ref::<Vec<MaybeRelocatable>>() {
177 self.load_data(ptr, vector).map(Into::into)
178 } else if let Some(vector) = arg.downcast_ref::<Vec<Relocatable>>() {
179 let data: &Vec<MaybeRelocatable> = &vector.iter().map(|value| value.into()).collect();
180 self.load_data(ptr, data).map(Into::into)
181 } else {
182 Err(MemoryError::WriteArg)
183 }
184 }
185
186 pub fn is_valid_memory_value(&self, value: &MaybeRelocatable) -> Result<bool, MemoryError> {
187 match &self.segment_used_sizes {
188 Some(segment_used_sizes) => match value {
189 MaybeRelocatable::Int(_) => Ok(true),
190 MaybeRelocatable::RelocatableValue(relocatable) => {
191 let segment_index: usize =
192 relocatable.segment_index.try_into().map_err(|_| {
193 MemoryError::AddressInTemporarySegment(relocatable.segment_index)
194 })?;
195
196 Ok(segment_index < segment_used_sizes.len())
197 }
198 },
199 None => Err(MemoryError::MissingSegmentUsedSizes),
200 }
201 }
202
203 pub fn is_accessed(&self, addr: &Relocatable) -> Result<bool, MemoryError> {
204 self.memory.is_accessed(addr)
205 }
206
207 pub fn get_memory_holes(
211 &self,
212 builtin_segment_indexes: HashSet<usize>,
213 ) -> Result<usize, MemoryError> {
214 let data = &self.memory.data;
215 let mut memory_holes = 0;
216 for i in 0..data.len() {
217 if builtin_segment_indexes.contains(&i) {
220 continue;
221 }
222 let accessed_amount =
223 if self.has_zero_segment() && i == self.zero_segment_index {
225 self.zero_segment_size
226 } else {
227 match self.memory.get_amount_of_accessed_addresses_for_segment(i) {
228 Some(accessed_amount) if accessed_amount > 0 => accessed_amount,
229 _ => continue,
230 }
231 };
232 let segment_size = self
233 .get_segment_size(i)
234 .ok_or(MemoryError::MissingSegmentUsedSizes)?;
235 if accessed_amount > segment_size {
236 return Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
237 Box::new((i, accessed_amount, segment_size)),
238 ));
239 }
240 memory_holes += segment_size - accessed_amount;
241 }
242 Ok(memory_holes)
243 }
244
245 pub fn get_public_memory_addresses(
248 &self,
249 segment_offsets: &[usize],
250 ) -> Result<Vec<(usize, usize)>, MemoryError> {
251 let mut addresses = Vec::with_capacity(self.num_segments());
252 let empty_vec = vec![];
253 for segment_index in 0..self.num_segments() {
254 let offsets = &self
255 .public_memory_offsets
256 .get(&segment_index)
257 .unwrap_or(&empty_vec);
258 let segment_start = segment_offsets
259 .get(segment_index)
260 .ok_or(MemoryError::MalformedPublicMemory)?;
261 for (offset, page_id) in offsets.iter() {
262 addresses.push((segment_start + offset, *page_id));
263 }
264 }
265 Ok(addresses)
266 }
267
268 pub fn finalize(
273 &mut self,
274 size: Option<usize>,
275 segment_index: usize,
276 public_memory: Option<&Vec<(usize, usize)>>,
277 ) {
278 if let Some(size) = size {
279 self.segment_sizes.insert(segment_index, size);
280 }
281 self.public_memory_offsets
282 .insert(segment_index, public_memory.cloned().unwrap_or_default());
283 }
284
285 pub fn has_zero_segment(&self) -> bool {
286 !self.zero_segment_index.is_zero()
287 }
288
289 pub(crate) fn add_zero_segment(&mut self, size: usize) -> usize {
293 if !self.has_zero_segment() {
294 self.zero_segment_index = self.add().segment_index as usize;
295 }
296
297 for _ in 0..(size.saturating_sub(self.zero_segment_size)) {
299 self.memory.data[self.zero_segment_index].push(MemoryCell::new(Felt252::ZERO.into()))
302 }
303 self.zero_segment_size = max(self.zero_segment_size, size);
304 self.zero_segment_index
305 }
306
307 pub(crate) fn finalize_zero_segment(&mut self) {
309 if self.has_zero_segment() {
310 self.finalize(Some(self.zero_segment_size), self.zero_segment_index, None);
311 self.zero_segment_index = 0;
312 self.zero_segment_size = 0;
313 }
314 }
315
316 pub(crate) fn load_pie_memory(
317 &mut self,
318 pie_memory: &CairoPieMemory,
319 n_extra_segments: usize,
320 ) -> Result<(), MemoryError> {
321 for _ in 0..n_extra_segments {
323 self.add();
324 }
325 for ((si, so), val) in pie_memory.0.iter() {
327 self.memory.insert((*si as isize, *so).into(), val)?;
328 }
329 Ok(())
330 }
331}
332
333impl Default for MemorySegmentManager {
334 fn default() -> Self {
335 Self::new()
336 }
337}
338
339impl fmt::Display for MemorySegmentManager {
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 writeln!(f, "Memory:\n{}", self.memory)?;
342 if let Some(used_sizes) = &self.segment_used_sizes {
343 writeln!(f, "Segment Info:")?;
344 for (index, used_size) in used_sizes.iter().enumerate() {
345 writeln!(
346 f,
347 "Segment Number: {}, Used Size: {}, Size {}",
348 index,
349 used_size,
350 self.segment_sizes
351 .get(&index)
352 .map(|n| n.to_string())
353 .unwrap_or(String::from("None"))
354 )?;
355 }
356 }
357 Ok(())
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364 use crate::Felt252;
365 use crate::{relocatable, utils::test_utils::*, vm::vm_memory::memory::MemoryCell};
366 use assert_matches::assert_matches;
367
368 #[cfg(target_arch = "wasm32")]
369 use wasm_bindgen_test::*;
370
371 #[test]
372 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
373 fn add_segment_no_size() {
374 let mut segments = MemorySegmentManager::new();
375 let base = segments.add();
376 assert_eq!(base, relocatable!(0, 0));
377 assert_eq!(segments.num_segments(), 1);
378 }
379
380 #[test]
381 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
382 fn add_segment_no_size_test_two_segments() {
383 let mut segments = MemorySegmentManager::new();
384 let mut _base = segments.add();
385 _base = segments.add();
386 assert_eq!(
387 _base,
388 Relocatable {
389 segment_index: 1,
390 offset: 0
391 }
392 );
393 assert_eq!(segments.num_segments(), 2);
394 }
395
396 #[test]
397 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
398 fn add_one_temporary_segment() {
399 let mut segments = MemorySegmentManager::new();
400 let base = segments.add_temporary_segment();
401 assert_eq!(base, relocatable!(-1, 0));
402 assert_eq!(segments.num_temp_segments(), 1);
403 }
404
405 #[test]
406 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
407 fn add_two_temporary_segments() {
408 let mut segments = MemorySegmentManager::new();
409 segments.add_temporary_segment();
410 let base = segments.add_temporary_segment();
411 assert_eq!(
412 base,
413 Relocatable {
414 segment_index: -2,
415 offset: 0
416 }
417 );
418 assert_eq!(segments.num_temp_segments(), 2);
419 }
420
421 #[test]
422 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
423 fn load_data_empty() {
424 let data = Vec::new();
425 let ptr = Relocatable::from((0, 3));
426 let mut segments = MemorySegmentManager::new();
427 let current_ptr = segments.load_data(ptr, &data).unwrap();
428 assert_eq!(current_ptr, Relocatable::from((0, 3)));
429 }
430
431 #[test]
432 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
433 fn load_data_one_element() {
434 let data = vec![MaybeRelocatable::from(Felt252::from(4))];
435 let ptr = Relocatable::from((0, 0));
436 let mut segments = MemorySegmentManager::new();
437 segments.add();
438 let current_ptr = segments.load_data(ptr, &data).unwrap();
439 assert_eq!(current_ptr, Relocatable::from((0, 1)));
440 assert_eq!(
441 segments.memory.get(&ptr).unwrap().as_ref(),
442 &MaybeRelocatable::from(Felt252::from(4))
443 );
444 }
445
446 #[test]
447 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
448 fn load_data_three_elements() {
449 let data = vec![
450 MaybeRelocatable::from(Felt252::from(4)),
451 MaybeRelocatable::from(Felt252::from(5)),
452 MaybeRelocatable::from(Felt252::from(6)),
453 ];
454 let ptr = Relocatable::from((0, 0));
455 let mut segments = MemorySegmentManager::new();
456 segments.add();
457 let current_ptr = segments.load_data(ptr, &data).unwrap();
458 assert_eq!(current_ptr, Relocatable::from((0, 3)));
459
460 assert_eq!(
461 segments.memory.get(&ptr).unwrap().as_ref(),
462 &MaybeRelocatable::from(Felt252::from(4))
463 );
464 assert_eq!(
465 segments
466 .memory
467 .get(&MaybeRelocatable::from((0, 1)))
468 .unwrap()
469 .as_ref(),
470 &MaybeRelocatable::from(Felt252::from(5))
471 );
472 assert_eq!(
473 segments
474 .memory
475 .get(&MaybeRelocatable::from((0, 2)))
476 .unwrap()
477 .as_ref(),
478 &MaybeRelocatable::from(Felt252::from(6))
479 );
480 }
481 #[test]
482 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
483 fn compute_effective_sizes_for_one_segment_memory() {
484 let mut segments = segments![((0, 0), 1), ((0, 1), 1), ((0, 2), 1)];
485 segments.compute_effective_sizes();
486 assert_eq!(Some(vec![3]), segments.segment_used_sizes);
487 }
488
489 #[test]
490 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
491 fn compute_effective_sizes_for_one_segment_memory_with_gap() {
492 let mut segments = MemorySegmentManager::new();
493 segments.add();
494 segments
495 .memory
496 .insert(
497 Relocatable::from((0, 6)),
498 &MaybeRelocatable::from(Felt252::from(1)),
499 )
500 .unwrap();
501 segments.compute_effective_sizes();
502 assert_eq!(Some(vec![7]), segments.segment_used_sizes);
503 }
504
505 #[test]
506 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
507 fn compute_effective_sizes_for_one_segment_memory_with_gaps() {
508 let mut segments = segments![((0, 3), 1), ((0, 4), 1), ((0, 7), 1), ((0, 9), 1)];
509 segments.compute_effective_sizes();
510 assert_eq!(Some(vec![10]), segments.segment_used_sizes);
511 }
512
513 #[test]
514 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
515 fn compute_effective_sizes_for_three_segment_memory() {
516 let mut segments = segments![
517 ((0, 0), 1),
518 ((0, 1), 1),
519 ((0, 2), 1),
520 ((1, 0), 1),
521 ((1, 1), 1),
522 ((1, 2), 1),
523 ((2, 0), 1),
524 ((2, 1), 1),
525 ((2, 2), 1)
526 ];
527 segments.compute_effective_sizes();
528 assert_eq!(Some(vec![3, 3, 3]), segments.segment_used_sizes);
529 }
530
531 #[test]
532 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
533 fn compute_effective_sizes_for_three_segment_memory_with_gaps() {
534 let mut segments = segments![
535 ((0, 2), 1),
536 ((0, 5), 1),
537 ((0, 7), 1),
538 ((1, 1), 1),
539 ((2, 2), 1),
540 ((2, 4), 1),
541 ((2, 7), 1)
542 ];
543 segments.compute_effective_sizes();
544 assert_eq!(Some(vec![8, 2, 8]), segments.segment_used_sizes);
545 }
546
547 #[test]
548 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
549 fn get_segment_used_size_after_computing_used() {
550 let mut segments = segments![
551 ((0, 2), 1),
552 ((0, 5), 1),
553 ((0, 7), 1),
554 ((1, 1), 1),
555 ((2, 2), 1),
556 ((2, 4), 1),
557 ((2, 7), 1)
558 ];
559 segments.compute_effective_sizes();
560 assert_eq!(Some(8), segments.get_segment_used_size(2));
561 }
562
563 #[test]
564 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
565 fn get_segment_used_size_before_computing_used() {
566 let segments = MemorySegmentManager::new();
567 assert_eq!(None, segments.get_segment_used_size(2));
568 }
569
570 #[test]
571 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
572 fn relocate_segments_one_segment() {
573 let mut segments = MemorySegmentManager::new();
574 segments.segment_used_sizes = Some(vec![3]);
575 assert_eq!(
576 segments
577 .relocate_segments()
578 .expect("Couldn't relocate after compute effective sizes"),
579 vec![1]
580 )
581 }
582
583 #[test]
584 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
585 fn relocate_segments_five_segment() {
586 let mut segments = MemorySegmentManager::new();
587 segments.segment_used_sizes = Some(vec![3, 3, 56, 78, 8]);
588 assert_eq!(
589 segments
590 .relocate_segments()
591 .expect("Couldn't relocate after compute effective sizes"),
592 vec![1, 4, 7, 63, 141]
593 )
594 }
595
596 #[test]
597 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
598 fn write_arg_relocatable() {
599 let data = vec![
600 Relocatable::from((0, 1)),
601 Relocatable::from((0, 2)),
602 Relocatable::from((0, 3)),
603 ];
604 let ptr = Relocatable::from((1, 0));
605 let mut segments = MemorySegmentManager::new();
606 for _ in 0..2 {
607 segments.add();
608 }
609
610 let exec = segments.write_arg(ptr, &data);
611
612 assert_eq!(exec, Ok(MaybeRelocatable::from((1, 3))));
613 assert_eq!(
614 segments.memory.data[1],
615 vec![
616 MemoryCell::new(MaybeRelocatable::from((0, 1))),
617 MemoryCell::new(MaybeRelocatable::from((0, 2))),
618 MemoryCell::new(MaybeRelocatable::from((0, 3))),
619 ]
620 );
621 }
622
623 #[test]
624 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
625 fn segment_default() {
626 let segment_mng_new = MemorySegmentManager::new();
627 let segment_mng_def: MemorySegmentManager = Default::default();
628 assert_eq!(
629 segment_mng_new.num_segments(),
630 segment_mng_def.num_segments()
631 );
632 assert_eq!(
633 segment_mng_new.segment_used_sizes,
634 segment_mng_def.segment_used_sizes
635 );
636 }
637
638 #[test]
639 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
640 fn is_valid_memory_value_missing_effective_sizes() {
641 let segment_manager = MemorySegmentManager::new();
642
643 assert_eq!(
644 segment_manager.is_valid_memory_value(&mayberelocatable!(0)),
645 Err(MemoryError::MissingSegmentUsedSizes),
646 );
647 }
648
649 #[test]
650 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
651 fn is_valid_memory_value_temporary_segment() {
652 let mut segment_manager = MemorySegmentManager::new();
653
654 segment_manager.segment_used_sizes = Some(vec![10]);
655 assert_eq!(
656 segment_manager.is_valid_memory_value(&mayberelocatable!(-1, 0)),
657 Err(MemoryError::AddressInTemporarySegment(-1)),
658 );
659 }
660
661 #[test]
662 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
663 fn is_valid_memory_value_invalid_segment() {
664 let mut segment_manager = MemorySegmentManager::new();
665
666 segment_manager.segment_used_sizes = Some(vec![10]);
667 assert_eq!(
668 segment_manager.is_valid_memory_value(&mayberelocatable!(1, 0)),
669 Ok(false),
670 );
671 }
672
673 #[test]
674 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
675 fn is_valid_memory_value() {
676 let mut segment_manager = MemorySegmentManager::new();
677
678 segment_manager.segment_used_sizes = Some(vec![10]);
679 assert_eq!(
680 segment_manager.is_valid_memory_value(&mayberelocatable!(0, 5)),
681 Ok(true),
682 );
683 }
684
685 #[test]
686 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
687 fn get_memory_holes_missing_segment_used_sizes() {
688 let mut memory_segment_manager = MemorySegmentManager::new();
689 memory_segment_manager.memory = memory![((0, 0), 0)];
690 memory_segment_manager
691 .memory
692 .mark_as_accessed((0, 0).into());
693 assert_eq!(
694 memory_segment_manager.get_memory_holes(HashSet::new()),
695 Err(MemoryError::MissingSegmentUsedSizes),
696 );
697 }
698
699 #[test]
700 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
701 fn get_memory_holes_out_of_address_offset_bigger_than_size() {
702 let mut memory_segment_manager = MemorySegmentManager::new();
703 memory_segment_manager.segment_used_sizes = Some(vec![2]);
704 memory_segment_manager.memory = memory![((0, 0), 1), ((0, 1), 1), ((0, 2), 2)];
705 for i in 0..3 {
706 memory_segment_manager
707 .memory
708 .mark_as_accessed((0, i).into());
709 }
710 assert_eq!(
711 memory_segment_manager.get_memory_holes(HashSet::new()),
712 Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
713 Box::new((0, 3, 2))
714 )),
715 );
716 }
717
718 #[test]
719 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
720 fn get_memory_holes_empty() {
721 let mut memory_segment_manager = MemorySegmentManager::new();
722 memory_segment_manager.segment_used_sizes = Some(Vec::new());
723 assert_eq!(
724 memory_segment_manager.get_memory_holes(HashSet::new()),
725 Ok(0),
726 );
727 }
728
729 #[test]
730 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
731 fn get_memory_holes_empty2() {
732 let mut memory_segment_manager = MemorySegmentManager::new();
733 memory_segment_manager.segment_used_sizes = Some(vec![4]);
734 assert_eq!(
735 memory_segment_manager.get_memory_holes(HashSet::new()),
736 Ok(0),
737 );
738 }
739
740 #[test]
741 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
742 fn get_memory_holes() {
743 let mut memory_segment_manager = MemorySegmentManager::new();
744 memory_segment_manager.segment_used_sizes = Some(vec![10]);
745 memory_segment_manager.memory = memory![
746 ((0, 0), 0),
747 ((0, 1), 0),
748 ((0, 2), 0),
749 ((0, 3), 0),
750 ((0, 6), 0),
751 ((0, 7), 0),
752 ((0, 8), 0),
753 ((0, 9), 0)
754 ];
755 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
756 memory_segment_manager
757 .memory
758 .mark_as_accessed((0, i).into());
759 }
760 assert_eq!(
761 memory_segment_manager.get_memory_holes(HashSet::new()),
762 Ok(2),
763 );
764 }
765
766 #[test]
767 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
768 fn get_memory_holes2() {
769 let mut memory_segment_manager = MemorySegmentManager::new();
770
771 memory_segment_manager.segment_sizes = HashMap::from([(0, 15)]);
772 memory_segment_manager.memory = memory![
773 ((0, 0), 0),
774 ((0, 1), 0),
775 ((0, 2), 0),
776 ((0, 3), 0),
777 ((0, 6), 0),
778 ((0, 7), 0),
779 ((0, 8), 0),
780 ((0, 9), 0)
781 ];
782 memory_segment_manager.segment_used_sizes = Some(vec![10]);
783 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
784 memory_segment_manager
785 .memory
786 .mark_as_accessed((0, i).into());
787 }
788 assert_eq!(
789 memory_segment_manager.get_memory_holes(HashSet::new()),
790 Ok(7),
791 );
792 }
793
794 #[test]
795 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
796 fn get_memory_size_missing_segment() {
797 let memory_segment_manager = MemorySegmentManager::new();
798
799 assert_eq!(memory_segment_manager.get_segment_size(0), None);
800 }
801
802 #[test]
803 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
804 fn get_memory_size_used() {
805 let mut memory_segment_manager = MemorySegmentManager::new();
806 memory_segment_manager.segment_used_sizes = Some(vec![5]);
807
808 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
809 }
810
811 #[test]
812 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
813 fn get_memory_size() {
814 let mut memory_segment_manager = MemorySegmentManager::new();
815 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
816
817 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
818 }
819
820 #[test]
821 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
822 fn get_memory_size2() {
823 let mut memory_segment_manager = MemorySegmentManager::new();
824 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
825 memory_segment_manager.segment_used_sizes = Some(vec![3]);
826
827 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
828 }
829
830 #[test]
833 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
834 fn gen_arg_relocatable() {
835 let mut memory_segment_manager = MemorySegmentManager::new();
836
837 assert_matches!(
838 memory_segment_manager.gen_arg(&mayberelocatable!(0, 0)),
839 Ok(x) if x == mayberelocatable!(0, 0)
840 );
841 }
842
843 #[test]
846 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
847 fn gen_arg_bigint() {
848 let mut memory_segment_manager = MemorySegmentManager::new();
849
850 assert_matches!(
851 memory_segment_manager.gen_arg(&mayberelocatable!(1234)),
852 Ok(x) if x == mayberelocatable!(1234)
853 );
854 }
855
856 #[test]
859 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
860 fn gen_arg_vec() {
861 let mut memory_segment_manager = MemorySegmentManager::new();
862
863 assert_matches!(
864 memory_segment_manager.gen_arg(
865 &vec![
866 mayberelocatable!(0),
867 mayberelocatable!(1),
868 mayberelocatable!(2),
869 mayberelocatable!(3),
870 mayberelocatable!(0, 0),
871 mayberelocatable!(0, 1),
872 mayberelocatable!(0, 2),
873 mayberelocatable!(0, 3),
874 ],
875 ),
876 Ok(x) if x == mayberelocatable!(0, 0)
877 );
878 }
879
880 #[test]
883 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
884 fn gen_arg_vec_relocatable() {
885 let mut memory_segment_manager = MemorySegmentManager::new();
886
887 assert_matches!(
888 memory_segment_manager.gen_arg(
889 &vec![
890 MaybeRelocatable::from((0, 0)),
891 MaybeRelocatable::from((0, 1)),
892 MaybeRelocatable::from((0, 2)),
893 MaybeRelocatable::from((0, 3)),
894 ],
895 ),
896 Ok(x) if x == mayberelocatable!(0, 0)
897 );
898 }
899
900 #[test]
903 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
904 fn gen_arg_invalid_type() {
905 let mut memory_segment_manager = MemorySegmentManager::new();
906
907 assert_matches!(
908 memory_segment_manager.gen_arg(&""),
909 Err(MemoryError::GenArgInvalidType)
910 );
911 }
912
913 #[test]
914 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
915 fn finalize_no_size_nor_memory() {
916 let mut segments = MemorySegmentManager::new();
917 segments.finalize(None, 0, None);
918 assert!(segments.memory.data.is_empty());
919 assert!(segments.memory.temp_data.is_empty());
920 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
921 assert_eq!(segments.num_segments(), 0);
922 assert_eq!(segments.num_temp_segments(), 0);
923 }
924
925 #[test]
926 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
927 fn finalize_no_memory() {
928 let mut segments = MemorySegmentManager::new();
929 segments.finalize(Some(42), 0, None);
930 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
931 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
932 }
933
934 #[test]
935 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
936 fn finalize_no_size() {
937 let mut segments = MemorySegmentManager::new();
938 segments.finalize(None, 0, Some(&vec![(1_usize, 2_usize)]));
939 assert_eq!(
940 segments.public_memory_offsets,
941 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
942 );
943 assert!(segments.segment_sizes.is_empty());
944 }
945
946 #[test]
947 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
948 fn finalize_all_args() {
949 let mut segments = MemorySegmentManager::new();
950 segments.finalize(Some(42), 0, Some(&vec![(1_usize, 2_usize)]));
951 assert_eq!(
952 segments.public_memory_offsets,
953 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
954 );
955 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
956 }
957
958 #[test]
959 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
960 fn gen_cairo_arg_single() {
961 let mut memory_segment_manager = MemorySegmentManager::new();
962
963 assert_matches!(
964 memory_segment_manager.gen_cairo_arg(&mayberelocatable!(1234).into()),
965 Ok(x) if x == mayberelocatable!(1234)
966 );
967 }
968
969 #[test]
970 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
971 fn gen_cairo_arg_array() {
972 let mut memory_segment_manager = MemorySegmentManager::new();
973
974 assert_matches!(
975 memory_segment_manager.gen_cairo_arg(
976 &vec![
977 mayberelocatable!(0),
978 mayberelocatable!(1),
979 mayberelocatable!(2),
980 mayberelocatable!(3),
981 mayberelocatable!(0, 0),
982 mayberelocatable!(0, 1),
983 mayberelocatable!(0, 2),
984 mayberelocatable!(0, 3),
985 ]
986 .into(),
987 ),
988 Ok(x) if x == mayberelocatable!(0, 0)
989 );
990 }
991
992 #[test]
993 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
994 fn gen_cairo_arg_composed() {
995 let mut memory_segment_manager = MemorySegmentManager::new();
996 let cairo_args = CairoArg::Composed(vec![
997 CairoArg::Array(vec![
998 mayberelocatable!(0),
999 mayberelocatable!(1),
1000 mayberelocatable!(2),
1001 ]),
1002 CairoArg::Single(mayberelocatable!(1234)),
1003 CairoArg::Single(mayberelocatable!(5678)),
1004 CairoArg::Array(vec![
1005 mayberelocatable!(3),
1006 mayberelocatable!(4),
1007 mayberelocatable!(5),
1008 ]),
1009 ]);
1010
1011 assert_matches!(
1012 memory_segment_manager.gen_cairo_arg(&cairo_args),
1013 Ok(x) if x == mayberelocatable!(2, 0)
1014 );
1015 }
1016
1017 #[test]
1018 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1019 fn test_add_zero_segment() {
1020 let mut memory_segment_manager = MemorySegmentManager::new();
1022 memory_segment_manager.add();
1023 memory_segment_manager.add();
1024
1025 memory_segment_manager.add_zero_segment(3);
1027 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1028 assert_eq!(memory_segment_manager.zero_segment_size, 3);
1029 assert_eq!(
1030 &memory_segment_manager.memory.data[2],
1031 &Vec::from([
1032 MemoryCell::new(MaybeRelocatable::from(0)),
1033 MemoryCell::new(MaybeRelocatable::from(0)),
1034 MemoryCell::new(MaybeRelocatable::from(0))
1035 ])
1036 );
1037
1038 memory_segment_manager.add_zero_segment(5);
1040 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1041 assert_eq!(memory_segment_manager.zero_segment_size, 5);
1042
1043 assert_eq!(
1044 &memory_segment_manager.memory.data[2],
1045 &Vec::from([
1046 MemoryCell::new(MaybeRelocatable::from(0)),
1047 MemoryCell::new(MaybeRelocatable::from(0)),
1048 MemoryCell::new(MaybeRelocatable::from(0)),
1049 MemoryCell::new(MaybeRelocatable::from(0)),
1050 MemoryCell::new(MaybeRelocatable::from(0))
1051 ])
1052 );
1053 }
1054}