This repository was archived by the owner on Oct 6, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtest_user_error.py
More file actions
174 lines (142 loc) · 5.46 KB
/
test_user_error.py
File metadata and controls
174 lines (142 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import re
from dataclasses import dataclass, field
from typing import Annotated, List
import pytest
from timefold.solver import *
from timefold.solver.config import *
from timefold.solver.domain import *
from timefold.solver.heuristic import *
from timefold.solver.score import *
@planning_entity
@dataclass
class Entity:
value: Annotated[str, PlanningVariable] = field(default=None)
@planning_solution
@dataclass
class Solution:
entity_list: Annotated[List[Entity], PlanningEntityCollectionProperty]
value_list: Annotated[List[str], ValueRangeProvider]
score: Annotated[SimpleScore, PlanningScore] = field(default=None)
@constraint_provider
def my_constraints(constraint_factory: ConstraintFactory):
return [
constraint_factory.for_each(Entity)
.penalize(SimpleScore.ONE, lambda entity: 'TEN') # noqa
.as_constraint('Penalize each entity')
]
def test_non_planning_solution_being_passed_to_solve():
solver_config = SolverConfig(
solution_class=Solution,
entity_class_list=[Entity],
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=my_constraints
)
)
solver = SolverFactory.create(solver_config).build_solver()
with pytest.raises(ValueError, match=re.escape(
f'The problem ({10}) is not an instance of the @planning_solution class'
)):
solver.solve(10)
def test_none_passed_to_solve():
solver_config = SolverConfig(
solution_class=Solution,
entity_class_list=[Entity],
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=my_constraints
)
)
solver = SolverFactory.create(solver_config).build_solver()
with pytest.raises(ValueError, match=re.escape(
f'The problem ({None}) is not an instance of the @planning_solution class'
)):
solver.solve(None)
def test_bad_return_type():
solver_config = SolverConfig(
solution_class=Solution,
entity_class_list=[Entity],
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=my_constraints
),
termination_config=TerminationConfig(
spent_limit=Duration(milliseconds=100)
)
)
problem = Solution([Entity()], ['1', '2', '3'])
solver = SolverFactory.create(solver_config).build_solver()
with pytest.raises(RuntimeError):
solver.solve(problem)
def test_non_proxied_class_passed():
class NonProxied:
pass
with pytest.raises(TypeError, match=re.escape(
f'is not a @planning_solution class'
)):
solver_config = SolverConfig(
solution_class=NonProxied
)._to_java_solver_config()
def test_non_proxied_function_passed():
def not_proxied():
pass
with pytest.raises(TypeError, match=re.escape(
f'is not a @constraint_provider function')):
solver_config = SolverConfig(
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=not_proxied # noqa
)
)._to_java_solver_config()
def test_constraint_construction_failed():
import inspect
line = inspect.getframeinfo(inspect.stack()[0][0]).lineno + 4
def bad_constraints(constraint_factory: ConstraintFactory):
return [
constraint_factory.for_each(BadEntity)
.penalize(SimpleScore.ONE)
.as_constraint('Penalize each entity')
]
bad_constraints = constraint_provider(bad_constraints)
solver_config = SolverConfig(
solution_class=Solution,
entity_class_list=[Entity],
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=bad_constraints
)
)
with pytest.raises(RuntimeError, match=re.escape(f'line {line}, in bad_constraints')):
SolverFactory.create(solver_config).build_solver()
def test_missing_enterprise():
with pytest.raises(RequiresEnterpriseError, match=re.escape('multithreaded solving')):
solver_config = SolverConfig(
move_thread_count=MoveThreadCount.AUTO
)._to_java_solver_config()
@nearby_distance_meter
def my_distance_meter(entity: Entity, value: str) -> float:
return 0.0
with pytest.raises(RequiresEnterpriseError, match=re.escape('nearby selection')):
solver_config = SolverConfig(
nearby_distance_meter_function=my_distance_meter
)._to_java_solver_config()
def test_using_collector_as_group_key():
@constraint_provider
def bad_constraints(constraint_factory: ConstraintFactory):
return [
constraint_factory.for_each(Entity)
.group_by(lambda entity: ConstraintCollectors.sum(10))
.penalize(SimpleScore.ONE)
.as_constraint("Minimize overtime")
]
solver_config = SolverConfig(
solution_class=Solution,
entity_class_list=[Entity],
score_director_factory_config=ScoreDirectorFactoryConfig(
constraint_provider_function=bad_constraints
),
termination_config=TerminationConfig(
score_calculation_count_limit=10
)
)
solver = SolverFactory.create(solver_config).build_solver()
problem = Solution([Entity()], ['1', '2', '3'])
with pytest.raises(TypeError, match=re.escape(
f'A ConstraintCollector should not be used as a key'
)):
solver.solve(problem)