app
SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
main
Drew Owens
0.9.0: bridge data moved out of the install cache (recovery survives updates), closed-in-place records, gates route thr…
5d02ca9
20d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
//! ADVERSARIAL REVIEW OF 0.7.5 — pass twenty-seven.
//!
//! The classifier change is right and the pass-26 findings are closed: the kind
//! is read from `GetType`, carried as a type NAME through `ready.docType`, and
//! re-parsed with `from_type_name` — never re-derived from the file name the
//! sweep itself chose. `from_extension` looks only at the last path segment, so
//! the `…\Drawings\` misclassification is gone. The `≥ original size` rule is
//! correctly scoped to `kind == None` only (`host.rs:431`), so a part that
//! legitimately shrinks — a suppressed feature, a deleted body, a lightweight
//! save — is still held to its own 24 KB floor and not to its old size. That
//! second half of the coordinator's question needed no change and got none.
//!
//! What is left is not the classifier. It is the two places the UNKNOWN branch
//! touches SOLIDWORKS, neither of which this suite can reach.
mod common;
use common::*;
use serde_json::json;
use swx_bridge::disk::DocKind;
fn s(v: &serde_json::Value) -> String {
serde_json::to_string_pretty(v).unwrap_or_default()
}
/// THE DOCUMENT'S OWN FILE PATH IS NOT CONSULTED.
///
/// The naming chain, verbatim from `com.rs:1086`:
///
/// ```ignore
/// let ext = match kind.or_else(|| DocKind::from_extension(title)) { … };
/// ```
///
/// `kind` is `GetType`, `title` is `GetTitle`. **`path` — `GetPathName`, which
/// the same function read four lines earlier and already uses for
/// `original_bytes` — is never asked.** It is the strongest evidence in the
/// room: the user's own file, named by SOLIDWORKS, on disk.
///
/// It matters because `GetTitle` does not reliably carry the extension.
/// SOLIDWORKS returns the title as the shell shows it, so with "hide extensions
/// for known file types" on — the Windows DEFAULT — a saved assembly's title is
/// `bracket`, not `bracket.SLDASM`. Combine that with one unreadable `GetType`
/// and a document whose kind is sitting in plain text in `path` is classified
/// unknown, named `.sldrecover`, and held to the drawing floor plus its original
/// size.
///
/// For a saved document that last part is survivable — refusing is loud and the
/// user's file is still on disk. The reason to fix it anyway is that it is one
/// `.or_else` against evidence already in hand, and it narrows the `.sldrecover`
/// path to the only case that truly has no extension anywhere: a pathless
/// document. Which is the case the next test is about.
#[test]
fn a_saved_assembly_is_classified_from_its_path_when_the_type_cannot_be_read() {
// GetType unreadable — the condition this sweep exists for.
let kind: Option<DocKind> = None;
// GetTitle with Explorer's default "hide extensions" setting.
let title = "bracket";
// GetPathName. Read four lines earlier in the same function, for size.
let path = "C:\\work\\bracket.SLDASM";
// The production expression, copied — as 0.7.6 fixed it. The path is asked
// before the title, because the title is the weaker evidence of the two:
// SOLIDWORKS reports it as the shell shows it, and Explorer hides known
// extensions by default.
let chosen = kind
.or_else(|| DocKind::from_extension(path))
.or_else(|| DocKind::from_extension(title));
assert!(
chosen.is_some(),
"a saved assembly was classified UNKNOWN while its kind was written in its own path, \
{path:?}. The naming chain asks GetType, then the TITLE's extension, and stops — it \
never asks the path, though the same function reads it for originalBytes. GetTitle \
carries no extension whenever Explorer hides known file types, which is the default."
);
}
/// WHAT `.sldrecover` COSTS, AND WHO IS TOLD.
///
/// `unique_recovery_path` gives an unknown-kind document the extension
/// `sldrecover`, which is not a format SOLIDWORKS knows. Two consequences, and
/// the bridge is silent about both.
///
/// FIRST, AND I CANNOT TEST IT HERE: `SaveAs3` dispatches its output format on
/// the extension. This codebase already knows that — `blocked_by_extension`
/// exists precisely because `.wrl` makes SaveAs3 raise a VRML option sheet, so
/// the extension demonstrably selects a writer. What `SaveAs3` does with an
/// extension matching NO writer is not something I will assert from memory; I
/// got a format claim wrong in pass 23 by doing exactly that. But there are only
/// two possibilities and both need an answer before a live run:
///
/// * It FAILS. The record says `preserved: false`, the document stays open,
/// nothing is lost — and 0.7.5's entire unknown-kind path (the strictest
/// floor, the `≥ original size` rule, this extension) is unreachable in
/// production, because the file it verifies is never written. A guard that
/// cannot be reached is the sixth this review has found shipping inert.
/// * It SUCCEEDS by falling back to some default writer. Then the bytes on
/// disk may not be the document's native format at all, and the marker check
/// would be validating a file whose format nobody chose.
///
/// The mock cannot distinguish these: it writes the file itself. Only the live
/// install can answer it, with one scripted `SaveAs3` to a junk extension on a
/// scratch document — which is a write, so it is not mine to run.
///
/// SECOND, AND THIS IS WHAT THE TEST PINS: if such a file IS written, it is the
/// rescue of a document that was never saved — the only copy of that work — and
/// SOLIDWORKS will not open it, because the shell and the dispatcher both go by
/// extension. `swx_recover_list` is the one verb that shows these files, and its
/// hint says "Reopen any of them with swx_open." For every `.sldrecover` file
/// that instruction is wrong, and nothing anywhere tells the user to rename it.
/// The verb has the file names in hand and could say so per file.
#[test]
fn recover_list_says_how_to_open_a_file_solidworks_will_not_open() {
let scratch = TempDir::new("adv26-recover");
let b = Bridge::start_in(TempDir::borrowed(&scratch.0), &[]);
// A sweep that preserved one document whose kind could not be established.
let root = scratch.join("recovery").join("2026-09-12T00-00-00");
std::fs::create_dir_all(&root).unwrap();
let mut body = vec![0u8; 400_000];
body[4..8].copy_from_slice(&[0x00, 0x00, 0x00, 0x04]);
std::fs::write(root.join("Assem1.sldrecover"), &body).unwrap();
let r = b.call("swx_recover_list", json!({}));
let text = s(&r).to_ascii_lowercase();
let listed = text.contains("sldrecover");
assert!(listed, "precondition: the unknown-kind rescue is listed at all: {}", s(&r));
assert!(
text.contains("rename") || text.contains("sldasm") || text.contains("extension"),
"swx_recover_list shows a .sldrecover file and tells the user \"Reopen any of them with \
swx_open\". SOLIDWORKS dispatches on extension, so that is the one instruction that \
cannot work for this file — and it is the rescue of a document that was NEVER SAVED, so \
it is the user's only copy. Nothing in the response mentions renaming it or what to \
rename it to. Response: {}",
s(&r)
);
}