blob: 1a8b4787dd3832f3c8fad6db00671b7b295720ab [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#! /usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2013-2015 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22"""Test cases for Toaster GUI and ReST."""
23
24from django.test import TestCase
25from django.core.urlresolvers import reverse
26from django.utils import timezone
27from orm.models import Project, Release, BitbakeVersion, Build
28from orm.models import ReleaseLayerSourcePriority, LayerSource, Layer
29from orm.models import Layer_Version, Recipe, Machine, ProjectLayer
30import json
31
32PROJECT_NAME = "test project"
33
34class ViewTests(TestCase):
35 """Tests to verify view APIs."""
36
37 def setUp(self):
38 bbv = BitbakeVersion.objects.create(name="test bbv", giturl="/tmp/",
39 branch="master", dirpath="")
40 release = Release.objects.create(name="test release",
41 bitbake_version=bbv)
42 self.project = Project.objects.create_project(name=PROJECT_NAME,
43 release=release)
44
45 layersrc = LayerSource.objects.create(sourcetype=LayerSource.TYPE_IMPORTED)
46 self.priority = ReleaseLayerSourcePriority.objects.create(release=release,
47 layer_source=layersrc)
48 layer = Layer.objects.create(name="base-layer", layer_source=layersrc,
49 vcs_url="/tmp/")
50
51 lver = Layer_Version.objects.create(layer=layer, project=self.project,
52 layer_source=layersrc, commit="master")
53
54 Recipe.objects.create(layer_source=layersrc, name="base-recipe",
55 version="1.2", summary="one recipe",
56 description="recipe", layer_version=lver)
57
58 Machine.objects.create(layer_version=lver, name="wisk",
59 description="wisking machine")
60
61 ProjectLayer.objects.create(project=self.project, layercommit=lver)
62
63 self.assertTrue(lver in self.project.compatible_layerversions())
64
65 def test_get_base_call_returns_html(self):
66 """Basic test for all-projects view"""
67 response = self.client.get(reverse('all-projects'), follow=True)
68 self.assertEqual(response.status_code, 200)
69 self.assertTrue(response['Content-Type'].startswith('text/html'))
70 self.assertTemplateUsed(response, "projects.html")
71 self.assertTrue(PROJECT_NAME in response.content)
72
73 def test_get_json_call_returns_json(self):
74 """Test for all projects output in json format"""
75 url = reverse('all-projects')
76 response = self.client.get(url, {"format": "json"}, follow=True)
77 self.assertEqual(response.status_code, 200)
78 self.assertTrue(response['Content-Type'].startswith('application/json'))
79
80 data = json.loads(response.content)
81
82 self.assertTrue("error" in data)
83 self.assertEqual(data["error"], "ok")
84 self.assertTrue("rows" in data)
85
86 self.assertTrue(PROJECT_NAME in [x["name"] for x in data["rows"]])
87 self.assertTrue("id" in data["rows"][0])
88
89 self.assertEqual(sorted(data["rows"][0]),
90 ['bitbake_version_id', 'created', 'id',
91 'is_default', 'layersTypeAheadUrl', 'name',
92 'num_builds', 'projectBuildsUrl', 'projectPageUrl',
93 'recipesTypeAheadUrl', 'release_id',
94 'short_description', 'updated', 'user_id'])
95
96 def test_typeaheads(self):
97 """Test typeahead ReST API"""
98 layers_url = reverse('xhr_layerstypeahead', args=(self.project.id,))
99 prj_url = reverse('xhr_projectstypeahead')
100
101 urls = [layers_url,
102 prj_url,
103 reverse('xhr_recipestypeahead', args=(self.project.id,)),
104 reverse('xhr_machinestypeahead', args=(self.project.id,)),
105 ]
106
107 def basic_reponse_check(response, url):
108 """Check data structure of http response."""
109 self.assertEqual(response.status_code, 200)
110 self.assertTrue(response['Content-Type'].startswith('application/json'))
111
112 data = json.loads(response.content)
113
114 self.assertTrue("error" in data)
115 self.assertEqual(data["error"], "ok")
116 self.assertTrue("results" in data)
117
118 # We got a result so now check the fields
119 if len(data['results']) > 0:
120 result = data['results'][0]
121
122 self.assertTrue(len(result['name']) > 0)
123 self.assertTrue("detail" in result)
124 self.assertTrue(result['id'] > 0)
125
126 # Special check for the layers typeahead's extra fields
127 if url == layers_url:
128 self.assertTrue(len(result['layerdetailurl']) > 0)
129 self.assertTrue(len(result['vcs_url']) > 0)
130 self.assertTrue(len(result['vcs_reference']) > 0)
131 # Special check for project typeahead extra fields
132 elif url == prj_url:
133 self.assertTrue(len(result['projectPageUrl']) > 0)
134
135 return True
136
137 return False
138
139 import string
140
141 for url in urls:
142 results = False
143
144 for typeing in list(string.ascii_letters):
145 response = self.client.get(url, {'search': typeing})
146 results = basic_reponse_check(response, url)
147 if results:
148 break
149
150 # After "typeing" the alpabet we should have result true
151 # from each of the urls
152 self.assertTrue(results)
153
154 def test_xhr_import_layer(self):
155 """Test xhr_importlayer API"""
156 #Test for importing an already existing layer
157 args = {'vcs_url' : "git://git.example.com/test",
158 'name' : "base-layer",
159 'git_ref': "c12b9596afd236116b25ce26dbe0d793de9dc7ce",
160 'project_id': 1, 'dir_path' : "/path/in/repository"}
161 response = self.client.post(reverse('xhr_importlayer'), args)
162 data = json.loads(response.content)
163 self.assertEqual(response.status_code, 200)
164 self.assertNotEqual(data["error"], "ok")
165
166 #Test to verify import of a layer successful
167 args['name'] = "meta-oe"
168 response = self.client.post(reverse('xhr_importlayer'), args)
169 data = json.loads(response.content)
170 self.assertTrue(data["error"], "ok")
171
172 #Test for html tag in the data
173 args['<'] = "testing html tag"
174 response = self.client.post(reverse('xhr_importlayer'), args)
175 data = json.loads(response.content)
176 self.assertNotEqual(data["error"], "ok")
177
178 #Empty data passed
179 args = {}
180 response = self.client.post(reverse('xhr_importlayer'), args)
181 data = json.loads(response.content)
182 self.assertNotEqual(data["error"], "ok")
183
184class LandingPageTests(TestCase):
185 """ Tests for redirects on the landing page """
186 # disable bogus pylint message error:
187 # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
188 # (see https://github.com/landscapeio/pylint-django/issues/42)
189 # pylint: disable=E1103
190
191 LANDING_PAGE_TITLE = 'This is Toaster'
192
193 def setUp(self):
194 """ Add default project manually """
195 self.project = Project.objects.create_project('foo', None)
196 self.project.is_default = True
197 self.project.save()
198
199 def test_only_default_project(self):
200 """
201 No projects except default
202 => get the landing page
203 """
204 response = self.client.get(reverse('landing'))
205 self.assertTrue(self.LANDING_PAGE_TITLE in response.content)
206
207 def test_default_project_has_build(self):
208 """
209 Default project has a build, no other projects
210 => get the builds page
211 """
212 now = timezone.now()
213 build = Build.objects.create(project=self.project,
214 started_on=now,
215 completed_on=now)
216 build.save()
217
218 response = self.client.get(reverse('landing'))
219 self.assertEqual(response.status_code, 302,
220 'response should be a redirect')
221 self.assertTrue('/builds' in response.url,
222 'should redirect to builds')
223
224 def test_user_project_exists(self):
225 """
226 User has added a project (without builds)
227 => get the projects page
228 """
229 user_project = Project.objects.create_project('foo', None)
230 user_project.save()
231
232 response = self.client.get(reverse('landing'))
233 self.assertEqual(response.status_code, 302,
234 'response should be a redirect')
235 self.assertTrue('/projects' in response.url,
236 'should redirect to projects')
237
238 def test_user_project_has_build(self):
239 """
240 User has added a project (with builds)
241 => get the builds page
242 """
243 user_project = Project.objects.create_project('foo', None)
244 user_project.save()
245
246 now = timezone.now()
247 build = Build.objects.create(project=user_project,
248 started_on=now,
249 completed_on=now)
250 build.save()
251
252 response = self.client.get(reverse('landing'))
253 self.assertEqual(response.status_code, 302,
254 'response should be a redirect')
255 self.assertTrue('/builds' in response.url,
256 'should redirect to builds')
257
258class ProjectsPageTests(TestCase):
259 """ Tests for projects page """
260
261 PROJECT_NAME = 'cli builds'
262
263 def setUp(self):
264 """ Add default project manually """
265 project = Project.objects.create_project(self.PROJECT_NAME, None)
266 self.default_project = project
267 self.default_project.is_default = True
268 self.default_project.save()
269
270 def test_default_project_hidden(self):
271 """ The default project should be hidden if it has no builds """
272 params = {"count": 10, "orderby": "updated:-", "page": 1}
273 response = self.client.get(reverse('all-projects'), params)
274
275 self.assertTrue(not('tr class="data"' in response.content),
276 'should be no project rows in the page')
277 self.assertTrue(not(self.PROJECT_NAME in response.content),
278 'default project "cli builds" should not be in page')
279
280 def test_default_project_has_build(self):
281 """ The default project should be shown if it has builds """
282 now = timezone.now()
283 build = Build.objects.create(project=self.default_project,
284 started_on=now,
285 completed_on=now)
286 build.save()
287
288 params = {"count": 10, "orderby": "updated:-", "page": 1}
289 response = self.client.get(reverse('all-projects'), params)
290
291 self.assertTrue('tr class="data"' in response.content,
292 'should be a project row in the page')
293 self.assertTrue(self.PROJECT_NAME in response.content,
294 'default project "cli builds" should be in page')