mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 21:11:56 +00:00
3610288029
Shim, FFI wrapper, difftest runner (3734 cases: fixtures, every label-table entry, 3000+ generated reports and add/contains sequences), all bit-identical. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
203 lines
7.7 KiB
C++
203 lines
7.7 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// difftest shim for unit `geom.assert_array`.
|
|
// Wraps upstream SmAssertReport / SmAssertArray / SM_GetAssertLabelList
|
|
// (source/SMLib/inc/SmAssertArray.h, source/SMLib/src/SmAssertArray.cpp).
|
|
//
|
|
// Object pointers are synthesised from integer keys (0 = NULL) and reported back
|
|
// as integers; upstream only stores and compares them, never dereferences them
|
|
// (SM_DEBUG_CODE is not defined in the reference build).
|
|
#include "sc_shim.h"
|
|
|
|
#include <SmTypes.h>
|
|
#include <SmTol.h>
|
|
#include <SmVector2d.h>
|
|
#include <SmAssertArray.h>
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace
|
|
{
|
|
// Integer fields of a report spec (keep in sync with crates/solidcore-ffi/src/units/geom_assert_array.rs).
|
|
enum SpecI : int
|
|
{
|
|
SI_REPORTER = 0,
|
|
SI_TEST_INDEX = 1,
|
|
SI_TEST_CLASS = 2,
|
|
SI_OWNER = 3,
|
|
SI_OWNER_TYPE = 4,
|
|
SI_OTHER = 5,
|
|
SI_OTHER_TYPE = 6,
|
|
SI_LIST_INDEX = 7,
|
|
SPEC_I_LEN = 8,
|
|
};
|
|
// Double fields of a report spec.
|
|
enum SpecD : int
|
|
{
|
|
SD_TOL = 0,
|
|
SD_VALUE = 1,
|
|
SPEC_D_LEN = 2,
|
|
};
|
|
// Integer fields of a report (output).
|
|
const int REPORT_I_LEN = 10;
|
|
// Double fields of a report (output).
|
|
const int REPORT_D_LEN = 7;
|
|
|
|
const void* key_ptr(int64_t k)
|
|
{
|
|
return reinterpret_cast<const void*>(static_cast<uintptr_t>(k));
|
|
}
|
|
|
|
int64_t ptr_key(const void* p)
|
|
{
|
|
return static_cast<int64_t>(reinterpret_cast<uintptr_t>(p));
|
|
}
|
|
|
|
SmAssertReport* make_report(const int64_t* si, const double* sd, const char* owner_ts,
|
|
const char* other_ts, const char* msg)
|
|
{
|
|
return new SmAssertReport(key_ptr(si[SI_REPORTER]), (ULONG)si[SI_TEST_INDEX],
|
|
(SM_TYPE)si[SI_TEST_CLASS], key_ptr(si[SI_OWNER]),
|
|
(SM_TYPE)si[SI_OWNER_TYPE], owner_ts, key_ptr(si[SI_OTHER]),
|
|
(SM_TYPE)si[SI_OTHER_TYPE], other_ts, SmTol3d(sd[SD_TOL]),
|
|
sd[SD_VALUE], (ULONG)si[SI_LIST_INDEX], msg);
|
|
}
|
|
|
|
void report_ints(const SmAssertReport& r, int64_t* o)
|
|
{
|
|
o[0] = r.m_bOK ? 1 : 0;
|
|
o[1] = ptr_key(r.m_pReporter);
|
|
o[2] = (int64_t)r.m_lReportingType;
|
|
o[3] = (int64_t)r.m_lListIndex;
|
|
o[4] = (int64_t)r.m_lTestIndex;
|
|
o[5] = (int64_t)r.m_eAssertType;
|
|
o[6] = ptr_key(r.GetOwner());
|
|
o[7] = (int64_t)r.GetOwnerType();
|
|
o[8] = ptr_key(r.GetOther());
|
|
o[9] = (int64_t)r.GetOtherType();
|
|
}
|
|
|
|
// Optional string argument: len < 0 = NULL.
|
|
const char* opt_str(const char* s, int64_t len, std::string& store)
|
|
{
|
|
if (len < 0)
|
|
return nullptr;
|
|
store.assign(s, (size_t)len);
|
|
return store.c_str();
|
|
}
|
|
|
|
// Appends string s (NULL -> length -1) to buf; records its length in lens[i].
|
|
void put_str(const char* s, std::string& buf, int64_t* lens, int i)
|
|
{
|
|
if (!s)
|
|
{
|
|
lens[i] = -1;
|
|
return;
|
|
}
|
|
lens[i] = (int64_t)std::strlen(s);
|
|
buf.append(s);
|
|
}
|
|
} // namespace
|
|
|
|
// Constructs one SmAssertReport, optionally calls SetValue / SetOwnerParam, and
|
|
// returns its fields.
|
|
// spec_i[8], spec_d[2] : see SpecI / SpecD
|
|
// owner_ts / other_ts / msg : strings with their lengths (-1 = NULL)
|
|
// set_value, value : when set_value != 0, call SetValue(value)
|
|
// set_owner_param, param[2] : when set_owner_param != 0, call SetOwnerParam(param)
|
|
// out_i[10] : ok, reporter, reporting type, list index, test index,
|
|
// assert type, owner, owner type, other, other type
|
|
// out_d[7] : tol3d, value, owner param (2), other param (2), dist3d
|
|
// str_lens[5] : lengths of name, message, message-for-file, owner type
|
|
// string, other type string (-1 = NULL), whose bytes are
|
|
// concatenated into out_s (capacity cap, *out_len bytes)
|
|
// The caller guarantees spec_i[SI_TEST_INDEX] is inside the label list.
|
|
SC_EXPORT int32_t sc_geom_assert_array_report(const int64_t* spec_i, const double* spec_d,
|
|
const char* owner_ts, int64_t owner_ts_len,
|
|
const char* other_ts, int64_t other_ts_len,
|
|
const char* msg, int64_t msg_len, int32_t set_value,
|
|
double value, int32_t set_owner_param,
|
|
const double* param, int64_t* out_i, double* out_d,
|
|
int64_t* str_lens, char* out_s, int64_t cap,
|
|
int64_t* out_len)
|
|
{
|
|
SC_TRY
|
|
std::string s_owner, s_other, s_msg;
|
|
const char* p_owner = opt_str(owner_ts, owner_ts_len, s_owner);
|
|
const char* p_other = opt_str(other_ts, other_ts_len, s_other);
|
|
const char* p_msg = opt_str(msg, msg_len, s_msg);
|
|
SmAssertReport* r = make_report(spec_i, spec_d, p_owner, p_other, p_msg);
|
|
if (set_value)
|
|
r->SetValue(value);
|
|
if (set_owner_param)
|
|
r->SetOwnerParam(SmPoint2d(param[0], param[1]));
|
|
report_ints(*r, out_i);
|
|
out_d[0] = (double)r->GetTol3d();
|
|
out_d[1] = r->GetValue();
|
|
out_d[2] = r->GetOwnerParam().x;
|
|
out_d[3] = r->GetOwnerParam().y;
|
|
out_d[4] = r->GetOtherParam().x;
|
|
out_d[5] = r->GetOtherParam().y;
|
|
out_d[6] = r->GetDist3d();
|
|
std::string buf;
|
|
put_str(r->m_pName, buf, str_lens, 0);
|
|
put_str(r->m_pMessage, buf, str_lens, 1);
|
|
put_str(r->m_pMessageForFile, buf, str_lens, 2);
|
|
put_str(r->m_sOwnerTypeString, buf, str_lens, 3);
|
|
put_str(r->m_sOtherTypeString, buf, str_lens, 4);
|
|
SmAssertReport::Delete(r);
|
|
return sc_copy_out(buf.data(), (int64_t)buf.size(), out_s, cap, out_len);
|
|
SC_CATCH
|
|
}
|
|
|
|
// Runs a sequence of operations on one SmAssertArray.
|
|
// kinds[n] : 0 = AddUniqueDeleteDuplicate(new report), 1 = SetLastAdd(flags[k]),
|
|
// 2 = Contains(report)
|
|
// flags[n] : SetLastAdd argument (kind 1)
|
|
// spec_i[n*8], spec_d[n*2] : report specs (kinds 0 and 2; strings are NULL)
|
|
// results[n] : AddUniqueDeleteDuplicate / Contains return (0/1), 0 for kind 1
|
|
// last_add[n] : GetLastAdd() after the operation
|
|
// out_elems : the final array, 10 ints per report (see report_ints);
|
|
// capacity cap ints, *out_len ints written
|
|
SC_EXPORT int32_t sc_geom_assert_array_sequence(int64_t n, const int32_t* kinds,
|
|
const int32_t* flags, const int64_t* spec_i,
|
|
const double* spec_d, int64_t* results,
|
|
int64_t* last_add, int64_t* out_elems,
|
|
int64_t cap, int64_t* out_len)
|
|
{
|
|
if (n < 0)
|
|
return SC_ERR_ARG;
|
|
SC_TRY
|
|
SmAssertArray arr;
|
|
for (int64_t k = 0; k < n; ++k)
|
|
{
|
|
const int64_t* si = spec_i + k * SPEC_I_LEN;
|
|
const double* sd = spec_d + k * SPEC_D_LEN;
|
|
results[k] = 0;
|
|
switch (kinds[k])
|
|
{
|
|
case 0: results[k] = arr.AddUniqueDeleteDuplicate(make_report(si, sd, NULL, NULL, NULL)) ? 1 : 0; break;
|
|
case 1: arr.SetLastAdd(flags[k] ? TRUE : FALSE); break;
|
|
case 2:
|
|
{
|
|
SmAssertReport* r = make_report(si, sd, NULL, NULL, NULL);
|
|
results[k] = arr.Contains(*r) ? 1 : 0;
|
|
SmAssertReport::Delete(r);
|
|
break;
|
|
}
|
|
default: return SC_ERR_ARG;
|
|
}
|
|
last_add[k] = (int64_t)arr.GetLastAdd();
|
|
}
|
|
std::vector<int64_t> elems;
|
|
for (ULONG i = 0; i < arr.GetSize(); ++i)
|
|
{
|
|
int64_t o[REPORT_I_LEN];
|
|
report_ints(*arr[i], o);
|
|
elems.insert(elems.end(), o, o + REPORT_I_LEN);
|
|
}
|
|
return sc_copy_out(elems.data(), (int64_t)elems.size(), out_elems, cap, out_len);
|
|
SC_CATCH
|
|
}
|