Initial commit
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
# Problem Query Methods - Giải Thích
|
||||
|
||||
## "Problem Query Methods" là gì?
|
||||
|
||||
**Problem Query Methods** là các methods trong class `Problem` dùng để **query (truy vấn) thông tin** về Problem, thay vì thay đổi trạng thái của Problem.
|
||||
|
||||
### Ví dụ:
|
||||
- ❌ **Non-query methods** (thay đổi trạng thái):
|
||||
- `AddParameterBlock()` - thêm parameter block
|
||||
- `SetParameterBlockConstant()` - đặt parameter block thành constant
|
||||
- `SetManifold()` - gán manifold cho parameter block
|
||||
|
||||
- ✅ **Query methods** (chỉ đọc thông tin):
|
||||
- `HasParameterBlock()` - kiểm tra parameter block có tồn tại không
|
||||
- `GetParameterBlockSize()` - lấy kích thước của parameter block
|
||||
- `IsParameterBlockConstant()` - kiểm tra parameter block có constant không
|
||||
- `HasManifold()` - kiểm tra parameter block có manifold không
|
||||
- `GetManifoldHandle()` - lấy manifold handle của parameter block
|
||||
|
||||
---
|
||||
|
||||
## So Sánh: C Test vs C# Test
|
||||
|
||||
### C Test (`test_problem_query_methods`) - Test 11
|
||||
|
||||
C test có **explicit tests** cho tất cả query methods:
|
||||
|
||||
```c
|
||||
// Test has_parameter_block
|
||||
int has_block = ceres_wrapper_problem_has_parameter_block(problem, params);
|
||||
TEST_ASSERT(has_block == 1, "Has parameter block");
|
||||
|
||||
// Test get_parameter_block_size
|
||||
int size = ceres_wrapper_problem_get_parameter_block_size(problem, params);
|
||||
TEST_ASSERT(size == 3, "Get parameter block size");
|
||||
|
||||
// Test is_parameter_block_constant
|
||||
int is_constant = ceres_wrapper_problem_is_parameter_block_constant(problem, params);
|
||||
TEST_ASSERT(is_constant == 0, "Parameter block is variable");
|
||||
|
||||
// Test has_manifold
|
||||
int has_manifold = ceres_wrapper_problem_has_manifold(problem, params);
|
||||
TEST_ASSERT(has_manifold == 0, "No manifold initially");
|
||||
|
||||
// Test get_manifold
|
||||
ceres_manifold_t* manifold = ceres_wrapper_problem_get_manifold(problem, params);
|
||||
TEST_ASSERT(manifold == NULL, "Get manifold returns NULL when no manifold");
|
||||
|
||||
// Test với non-existent parameter block
|
||||
double fake_params[2] = {99.0, 99.0};
|
||||
has_block = ceres_wrapper_problem_has_parameter_block(problem, fake_params);
|
||||
TEST_ASSERT(has_block == 0, "Non-existent parameter block");
|
||||
|
||||
size = ceres_wrapper_problem_get_parameter_block_size(problem, fake_params);
|
||||
TEST_ASSERT(size == -1, "Get size returns -1 for non-existent block");
|
||||
```
|
||||
|
||||
### C# Test - Hiện Tại
|
||||
|
||||
C# test **chỉ có tests** cho:
|
||||
- ✅ `IsParameterBlockConstant()` - có 2 tests
|
||||
- `IsParameterBlockConstant_ShouldReturnFalse_WhenVariable`
|
||||
- `IsParameterBlockConstant_ShouldReturnTrue_WhenConstant`
|
||||
|
||||
**Thiếu tests** cho:
|
||||
- ❌ `HasParameterBlock()` - chưa có test
|
||||
- ❌ `GetParameterBlockSize()` - chưa có test
|
||||
- ❌ `HasManifold()` - chưa có test
|
||||
- ❌ `GetManifoldHandle()` - chưa có test
|
||||
- ❌ `GetParameterBlockTangentSize()` - chưa có test
|
||||
|
||||
---
|
||||
|
||||
## Tại Sao Cần Test Query Methods?
|
||||
|
||||
### 1. **Verify API Works Correctly**
|
||||
Đảm bảo các methods trả về đúng giá trị:
|
||||
- `HasParameterBlock()` trả về `true` khi parameter block tồn tại
|
||||
- `GetParameterBlockSize()` trả về đúng kích thước
|
||||
- `HasManifold()` trả về `true` sau khi set manifold
|
||||
|
||||
### 2. **Edge Cases**
|
||||
Test các trường hợp đặc biệt:
|
||||
- Query parameter block không tồn tại → trả về `false` hoặc `-1`
|
||||
- Query manifold khi chưa set → trả về `false` hoặc `IntPtr.Zero`
|
||||
- Query size của non-existent block → trả về `-1`
|
||||
|
||||
### 3. **Integration với Other Operations**
|
||||
Verify query methods hoạt động đúng sau các operations:
|
||||
- Sau `AddParameterBlock()` → `HasParameterBlock()` = `true`
|
||||
- Sau `SetManifold()` → `HasManifold()` = `true`
|
||||
- Sau `SetParameterBlockConstant()` → `IsParameterBlockConstant()` = `true`
|
||||
|
||||
---
|
||||
|
||||
## Các Methods Cần Test
|
||||
|
||||
### 1. `HasParameterBlock(double[] parameters)`
|
||||
**Mục đích**: Kiểm tra parameter block có tồn tại trong Problem không
|
||||
|
||||
**Test cases cần có**:
|
||||
```csharp
|
||||
[Test]
|
||||
public void HasParameterBlock_ShouldReturnTrue_WhenExists()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var parameters = new double[] { 1.0, 2.0 };
|
||||
problem.AddParameterBlock(parameters, parameters.Length);
|
||||
|
||||
var hasBlock = problem.HasParameterBlock(parameters);
|
||||
|
||||
Assert.That(hasBlock, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasParameterBlock_ShouldReturnFalse_WhenNotExists()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var parameters = new double[] { 1.0, 2.0 };
|
||||
var fakeParams = new double[] { 99.0, 99.0 };
|
||||
|
||||
problem.AddParameterBlock(parameters, parameters.Length);
|
||||
|
||||
var hasBlock = problem.HasParameterBlock(fakeParams);
|
||||
|
||||
Assert.That(hasBlock, Is.False);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. `GetParameterBlockSize(double[] parameters)`
|
||||
**Mục đích**: Lấy kích thước của parameter block
|
||||
|
||||
**Test cases cần có**:
|
||||
```csharp
|
||||
[Test]
|
||||
public void GetParameterBlockSize_ShouldReturnCorrectSize()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var parameters = new double[] { 1.0, 2.0, 3.0 };
|
||||
problem.AddParameterBlock(parameters, parameters.Length);
|
||||
|
||||
var size = problem.GetParameterBlockSize(parameters);
|
||||
|
||||
Assert.That(size, Is.EqualTo(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetParameterBlockSize_ShouldReturnMinusOne_WhenNotExists()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var fakeParams = new double[] { 99.0, 99.0 };
|
||||
|
||||
var size = problem.GetParameterBlockSize(fakeParams);
|
||||
|
||||
Assert.That(size, Is.EqualTo(-1));
|
||||
}
|
||||
```
|
||||
|
||||
### 3. `HasManifold(double[] parameters)`
|
||||
**Mục đích**: Kiểm tra parameter block có manifold không
|
||||
|
||||
**Test cases cần có**:
|
||||
```csharp
|
||||
[Test]
|
||||
public void HasManifold_ShouldReturnFalse_WhenNoManifold()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var parameters = new double[] { 1.0, 2.0, 3.0, 4.0 };
|
||||
problem.AddParameterBlock(parameters, parameters.Length);
|
||||
|
||||
var hasManifold = problem.HasManifold(parameters);
|
||||
|
||||
Assert.That(hasManifold, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasManifold_ShouldReturnTrue_WhenManifoldSet()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var quaternion = new double[] { 0.0, 0.0, 0.0, 1.0 };
|
||||
problem.AddParameterBlock(quaternion, quaternion.Length);
|
||||
|
||||
using var manifold = new QuaternionManifold();
|
||||
problem.SetManifold(quaternion, manifold);
|
||||
|
||||
var hasManifold = problem.HasManifold(quaternion);
|
||||
|
||||
Assert.That(hasManifold, Is.True);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. `GetManifoldHandle(double[] parameters)`
|
||||
**Mục đích**: Lấy native handle của manifold (trả về `IntPtr.Zero` nếu không có)
|
||||
|
||||
**Test cases cần có**:
|
||||
```csharp
|
||||
[Test]
|
||||
public void GetManifoldHandle_ShouldReturnZero_WhenNoManifold()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var parameters = new double[] { 1.0, 2.0 };
|
||||
problem.AddParameterBlock(parameters, parameters.Length);
|
||||
|
||||
var handle = problem.GetManifoldHandle(parameters);
|
||||
|
||||
Assert.That(handle, Is.EqualTo(IntPtr.Zero));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetManifoldHandle_ShouldReturnNonZero_WhenManifoldSet()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var quaternion = new double[] { 0.0, 0.0, 0.0, 1.0 };
|
||||
problem.AddParameterBlock(quaternion, quaternion.Length);
|
||||
|
||||
using var manifold = new QuaternionManifold();
|
||||
problem.SetManifold(quaternion, manifold);
|
||||
|
||||
var handle = problem.GetManifoldHandle(quaternion);
|
||||
|
||||
Assert.That(handle, Is.Not.EqualTo(IntPtr.Zero));
|
||||
}
|
||||
```
|
||||
|
||||
### 5. `GetParameterBlockTangentSize(double[] parameters)`
|
||||
**Mục đích**: Lấy tangent size của parameter block (khi có manifold)
|
||||
|
||||
**Test cases cần có**:
|
||||
```csharp
|
||||
[Test]
|
||||
public void GetParameterBlockTangentSize_ShouldReturnTangentSize_WithManifold()
|
||||
{
|
||||
using var problem = new Problem();
|
||||
var quaternion = new double[] { 0.0, 0.0, 0.0, 1.0 }; // 4D ambient
|
||||
problem.AddParameterBlock(quaternion, quaternion.Length);
|
||||
|
||||
using var manifold = new QuaternionManifold(); // 3D tangent
|
||||
problem.SetManifold(quaternion, manifold);
|
||||
|
||||
var tangentSize = problem.GetParameterBlockTangentSize(quaternion);
|
||||
|
||||
Assert.That(tangentSize, Is.EqualTo(3)); // Quaternion: 4D ambient → 3D tangent
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kết Luận
|
||||
|
||||
### Hiện Tại
|
||||
- ✅ C# API **đã implement** tất cả query methods
|
||||
- ✅ C# test **đã có** test cho `IsParameterBlockConstant()`
|
||||
- ❌ C# test **thiếu** tests cho 5 methods còn lại
|
||||
|
||||
### Khuyến Nghị
|
||||
1. **Nên thêm tests** cho các query methods để:
|
||||
- Đảm bảo API hoạt động đúng
|
||||
- Test edge cases (non-existent blocks, null parameters)
|
||||
- Verify integration với các operations khác
|
||||
|
||||
2. **Priority**:
|
||||
- **High**: `HasParameterBlock()`, `GetParameterBlockSize()` - thường dùng
|
||||
- **Medium**: `HasManifold()`, `GetManifoldHandle()` - dùng khi làm việc với manifolds
|
||||
- **Low**: `GetParameterBlockTangentSize()` - ít dùng, nhưng nên có test
|
||||
|
||||
3. **Impact**:
|
||||
- Không ảnh hưởng đến production (API đã implement đúng)
|
||||
- Nhưng thiếu tests có thể dẫn đến bugs không được phát hiện khi refactor
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2024-12-19
|
||||
Reference in New Issue
Block a user