#11545 closed defect (fixed)
Search returns milestone resource when only one word matches
| Reported by: | Ryan J Ollos | Owned by: | Ryan J Ollos |
|---|---|---|---|
| Priority: | normal | Milestone: | 1.0.2 |
| Component: | search system | Version: | 1.0-stable |
| Severity: | normal | Keywords: | roadmap |
| Cc: | Branch: | ||
| Release Notes: |
Fixed milestone search returning results when only one word from phrase matched. |
||
| API Changes: | |||
| Internal Changes: | |||
Description (last modified by )
For a long time I've been noticing that the milestones would almost always appear in my search results, even for cases that I wouldn't expect them to appear. It looks like a milestone will be returned in the search results when there is a match from only one word of a multiword phrase.
The following test was done to prove the case:
- Generated 3 words at http://listofrandomwords.com: Semiphilosophic opportunistic sulphur
- Created 4 tickets: one ticket with the phrase as the summary and three tickets containing one word of the phrase as the summary.
- Created 4 tickets: one ticket with the phrase as the description and three tickets containing one word of the phrase as the description.
- Created 4 milestones: one milestone with the phrase in the description and three milestones containing one word of the phrase in the description.
- Created 4 wiki pages: one wiki page with the phrase in the content and three wiki pages containing one word of the phrase in the content.
Here are the search results:
Attachments (1)
Change History (13)
by , 12 years ago
| Attachment: | SearchResults.png added |
|---|
comment:1 by , 12 years ago
comment:2 by , 12 years ago
| Description: | modified (diff) |
|---|
comment:3 by , 12 years ago
Good catch! Right, all() seems appropriate to reproduce the behavior of the former SQL query in trunk/trac/search/api.py@11528#L54.
comment:4 by , 12 years ago
| Milestone: | next-stable-1.0.x → 1.0.2 |
|---|---|
| Owner: | set to |
| Status: | new → assigned |
Thanks for providing a fix. I've prepared the change along with a unit test in log:rjollos.git:t11545.
comment:5 by , 12 years ago
| Release Notes: | modified (diff) |
|---|---|
| Resolution: | → fixed |
| Status: | assigned → closed |
comment:6 by , 12 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → reopened |
After [12593], I got the following.
======================================================================
ERROR: test_get_search_results_milestone_not_in_filters (trac.ticket.tests.roadmap.MilestoneModuleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/ticket/tests/roadmap.py", line 155, in setUp
m.insert()
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/ticket/model.py", line 1042, in insert
to_utimestamp(self.completed), self.description))
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/db/util.py", line 121, in execute
cursor.execute(query, params)
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/db/util.py", line 54, in execute
r = self.cursor.execute(sql_escape_percent(sql), args)
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/db/sqlite_backend.py", line 78, in execute
result = PyFormatCursor.execute(self, *args)
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/db/sqlite_backend.py", line 56, in execute
args or [])
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/db/sqlite_backend.py", line 48, in _rollback_on_error
return function(self, *args, **kwargs)
IntegrityError: column name is not unique
======================================================================
FAIL: test_get_search_results_matches_all_terms (trac.ticket.tests.roadmap.MilestoneModuleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jun66j5/src/trac/edgewall/svn/branches/1.0-stable/trac/ticket/tests/roadmap.py", line 174, in test_get_search_results_matches_all_terms
self.assertEqual(1, len(results))
AssertionError: 1 != 2
I've investigated.
- We must call
reset_db()intearDown()in the case. - If
/usr/share/dict/wordsmight not be existent,random_word()generates using 10 words at most.
-
trac/ticket/tests/roadmap.py
diff --git a/trac/ticket/tests/roadmap.py b/trac/ticket/tests/roadmap.py index 31dbb7c..d7fab12 100644
a b class MilestoneModuleTestCase(unittest.TestCase): 145 145 self.env = EnvironmentStub() 146 146 self.req = Mock(href=self.env.href, perm=MockPerm()) 147 147 self.mmodule = MilestoneModule(self.env) 148 self.terms = [random_word() for i in range(0, 3)] 148 terms = set() 149 while len(terms) != 3: 150 terms.add(random_word()) 151 self.terms = list(terms) 149 152 self.milestones = [] 150 153 for term in self.terms + [' '.join(self.terms)]: 151 154 m = Milestone(self.env) … … class MilestoneModuleTestCase(unittest.TestCase): 155 158 m.insert() 156 159 self.milestones.append(m) 157 160 161 def tearDown(self): 162 self.env.reset_db() 163 158 164 def test_get_search_filters(self): 159 165 filters = self.mmodule.get_search_filters(self.req) 160 166 filters = list(filters)
comment:7 by , 12 years ago
Okay, thanks. Maybe we should add random_unique_words(word_count, min_length=1) to trac.tests.contentgen.
comment:8 by , 12 years ago
Also, I noticed that the /usr/share/dict/words file has words which contains other words, e.g. in v.s. winch. That terms are not unique.
It would be simple to be hard-coded rather than random_word().
- self.terms = [random_word() for i in range(0, 3)] + self.terms = ['MilestoneAlpha', 'MilestoneBeta', 'MilestoneGamma']
comment:9 by , 12 years ago
| Resolution: | → fixed |
|---|---|
| Status: | reopened → closed |
follow-up: 11 comment:10 by , 12 years ago
I was confused as to why it didn't seem to be necessary to call reset_db in tearDown, but it appears that is due to the reset_db call in the EnvironmentStub constructor: branches/1.0-stable/trac/test.py@12531:311-312#L292. Is there a reason to also call reset_db in tearDown?
I found the destroying parameter to be a bit confusing. It appears to mean, don't initialize the database because the EnvironmentStub object is being constructed to call destroy_db. At least, that is the use-case in trac.tests.functional.testenv:FunctionalTestEnvironment. Initially I assumed it meant, construct a EnvironmentStub object and destroy existing data in the db. I'll add an entry in the docstring to clarify the behavior.
comment:11 by , 12 years ago
Is there a reason to also call
reset_dbintearDown?
The failures have gone away on r12603. But I still think we should call the reset_db to keep the database clean.
All test cases should reset database in tearDown() if records are created by setUp() or the test methods of the test case. Also, I don't think that the next test case always calls reset_db() from EnvironmentStub().




I think it was changed in [11525] and could be fixed by changing any() to
all(). (untested)