Mercurial
comparison infinite_canvas/canvas_test.c @ 280:49e9e591c9bb
Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 18 Aug 2026 19:14:53 -0700 |
| parents | 8d560f50ed4c |
| children | c57149ad216e |
comparison
equal
deleted
inserted
replaced
| 279:b3b547563ec7 | 280:49e9e591c9bb |
|---|---|
| 524 assert(small_context[sizeof(small_context) - 1] == '\0'); | 524 assert(small_context[sizeof(small_context) - 1] == '\0'); |
| 525 | 525 |
| 526 Dowa_Arena_Free(p_arena); | 526 Dowa_Arena_Free(p_arena); |
| 527 } | 527 } |
| 528 | 528 |
| 529 static void Test_Dictation_Scratchpad_Is_Not_A_Routing_Target(void) | |
| 530 { | |
| 531 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE); | |
| 532 assert(p_arena); | |
| 533 | |
| 534 Canvas_Camera camera; | |
| 535 Canvas_Camera_Init(&camera, 800, 600); | |
| 536 Canvas_Scene scene; | |
| 537 Canvas_Scene_Init(&scene, p_arena); | |
| 538 assert(Canvas_Scene_Add( | |
| 539 &scene, | |
| 540 CANVAS_ENTITY_TEXT_AREA, | |
| 541 (Vector2){-260.0f, -120.0f})); | |
| 542 snprintf( | |
| 543 scene.p_entities[0].label, | |
| 544 sizeof(scene.p_entities[0].label), | |
| 545 "Dictation"); | |
| 546 snprintf( | |
| 547 scene.p_entities[0].text, | |
| 548 sizeof(scene.p_entities[0].text), | |
| 549 "Route this thought"); | |
| 550 uint32 conversation_id = Canvas_Scene_Add_Conversation( | |
| 551 &scene, | |
| 552 "Visible session", | |
| 553 "Earlier thought", | |
| 554 "Earlier response", | |
| 555 (Vector2){40.0f, -120.0f}); | |
| 556 assert(conversation_id != 0); | |
| 557 | |
| 558 char context[4096]; | |
| 559 Canvas_Context_Snapshot snapshot = Canvas_Scene_Build_Visible_Context( | |
| 560 &scene, | |
| 561 &camera, | |
| 562 context, | |
| 563 sizeof(context)); | |
| 564 assert(snapshot.visible_count == 1); | |
| 565 assert(!strstr(context, "Route this thought")); | |
| 566 assert(strstr(context, "Visible session")); | |
| 567 assert(strstr(context, TextFormat("id=%u", conversation_id))); | |
| 568 | |
| 569 Dowa_Arena_Free(p_arena); | |
| 570 } | |
| 571 | |
| 572 static void Test_Conversation_Create_And_Append(void) | |
| 573 { | |
| 574 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE); | |
| 575 assert(p_arena); | |
| 576 Canvas_Scene scene; | |
| 577 Canvas_Scene_Init(&scene, p_arena); | |
| 578 | |
| 579 uint32 id = Canvas_Scene_Add_Conversation( | |
| 580 &scene, | |
| 581 "Rendering architecture", | |
| 582 "How should images render?", | |
| 583 "Use a rich entity with typed resources.", | |
| 584 (Vector2){10.0f, 20.0f}); | |
| 585 assert(id != 0); | |
| 586 assert(Dowa_Array_Length(scene.p_entities) == 1); | |
| 587 assert(scene.p_entities[0].type == CANVAS_ENTITY_CONVERSATION); | |
| 588 assert(strcmp(scene.p_entities[0].label, "Rendering architecture") == 0); | |
| 589 assert(strstr(scene.p_entities[0].text, "How should images render?")); | |
| 590 | |
| 591 assert(Canvas_Scene_Append_Conversation( | |
| 592 &scene, | |
| 593 id, | |
| 594 "What about browser content?", | |
| 595 "Keep the resource typed and composited by its backend.")); | |
| 596 assert(strstr(scene.p_entities[0].text, "What about browser content?")); | |
| 597 assert(strstr(scene.p_entities[0].text, "composited by its backend")); | |
| 598 assert(!Canvas_Scene_Append_Conversation( | |
| 599 &scene, | |
| 600 id + 1, | |
| 601 "Missing", | |
| 602 "Missing")); | |
| 603 Dowa_Arena_Free(p_arena); | |
| 604 } | |
| 605 | |
| 606 static void Test_Conversation_Collapse_And_Parking(void) | |
| 607 { | |
| 608 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE); | |
| 609 assert(p_arena); | |
| 610 Canvas_Camera camera; | |
| 611 Canvas_Camera_Init(&camera, 800, 600); | |
| 612 Canvas_Scene scene; | |
| 613 Canvas_Scene_Init(&scene, p_arena); | |
| 614 | |
| 615 Vector2 original = {20.0f, 30.0f}; | |
| 616 uint32 id = Canvas_Scene_Add_Conversation( | |
| 617 &scene, | |
| 618 "Parkable session", | |
| 619 "Question", | |
| 620 "Answer", | |
| 621 original); | |
| 622 Canvas_Entity *p_conversation = &scene.p_entities[0]; | |
| 623 assert(Near(p_conversation->animation_amount, 1.0f)); | |
| 624 Canvas_Conversation_Set_Collapsed(p_conversation, TRUE); | |
| 625 assert(p_conversation->active); | |
| 626 Canvas_Conversation_Set_Collapsed(p_conversation, FALSE); | |
| 627 assert(!p_conversation->active); | |
| 628 | |
| 629 assert(Canvas_Scene_Set_Conversation_Parked(&scene, id, TRUE)); | |
| 630 assert(p_conversation->parked); | |
| 631 assert(Canvas_Scene_Parked_Conversation_Count(&scene) == 1); | |
| 632 assert(!Near(p_conversation->position.x, original.x)); | |
| 633 char context[4096]; | |
| 634 Canvas_Context_Snapshot snapshot = Canvas_Scene_Build_Visible_Context( | |
| 635 &scene, | |
| 636 &camera, | |
| 637 context, | |
| 638 sizeof(context)); | |
| 639 assert(snapshot.visible_count == 0); | |
| 640 assert(Canvas_Scene_Show_Parking_Lot(&scene, &camera)); | |
| 641 snapshot = Canvas_Scene_Build_Visible_Context( | |
| 642 &scene, | |
| 643 &camera, | |
| 644 context, | |
| 645 sizeof(context)); | |
| 646 assert(snapshot.visible_count == 0); | |
| 647 | |
| 648 assert(Canvas_Scene_Set_Conversation_Parked(&scene, id, FALSE)); | |
| 649 assert(!p_conversation->parked); | |
| 650 assert(Canvas_Scene_Parked_Conversation_Count(&scene) == 0); | |
| 651 assert(Near(p_conversation->position.x, original.x)); | |
| 652 assert(Near(p_conversation->position.y, original.y)); | |
| 653 Dowa_Arena_Free(p_arena); | |
| 654 } | |
| 655 | |
| 529 int main(void) | 656 int main(void) |
| 530 { | 657 { |
| 531 Test_Theme_Resolution(); | 658 Test_Theme_Resolution(); |
| 532 Test_Camera_Round_Trip(); | 659 Test_Camera_Round_Trip(); |
| 533 Test_Anchored_Zoom(); | 660 Test_Anchored_Zoom(); |
| 541 Test_Entity_Fade_Lifecycle_Commands(); | 668 Test_Entity_Fade_Lifecycle_Commands(); |
| 542 Test_Browser_Grid(); | 669 Test_Browser_Grid(); |
| 543 Test_Lucide_Gallery_Reuses_Entity_And_Fits_Camera(); | 670 Test_Lucide_Gallery_Reuses_Entity_And_Fits_Camera(); |
| 544 Test_Lucide_Search_Is_Case_Insensitive(); | 671 Test_Lucide_Search_Is_Case_Insensitive(); |
| 545 Test_Demo_Contains_Every_Entity_Type(); | 672 Test_Demo_Contains_Every_Entity_Type(); |
| 673 Test_Conversation_Create_And_Append(); | |
| 546 Test_Pinned_Entity_Stays_In_Screen_Space(); | 674 Test_Pinned_Entity_Stays_In_Screen_Space(); |
| 547 Test_Visible_Context_Tracks_Camera_And_Values(); | 675 Test_Visible_Context_Tracks_Camera_And_Values(); |
| 676 Test_Dictation_Scratchpad_Is_Not_A_Routing_Target(); | |
| 677 Test_Conversation_Collapse_And_Parking(); | |
| 548 printf("Infinite canvas tests passed.\n"); | 678 printf("Infinite canvas tests passed.\n"); |
| 549 return 0; | 679 return 0; |
| 550 } | 680 } |