blob: d7a7c6049196fdbe07c41ef5c554223b7d805fa2 [file] [log] [blame]
# Copyright 2013 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for MapReduce job to apply organization acceptance/rejection."""
import collections
from google.appengine.ext import ndb
from mapreduce import test_support
from melange.models import organization as org_model
from soc.logic.helper import notifications
from soc.models import program as program_model
from soc.mapreduce.helper import control as mapreduce_control
from soc.modules.seeder.logic.seeder import logic as seeder_logic
from seeder import profile as profile_seeder
from tests import org_utils
from tests import test_utils
_TEST_ORGS_PER_STATUS = 4
_TEST_NUMBER_OF_ORG_ADMINS = 6
class TestApplyOrgAdmissionDecisions(test_utils.GSoCDjangoTestCase):
"""Unit tests for ApplyOrgAdmissionDecisions MapReduce job."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
# seed a few organizations; some of them are pre-rejected, some are
# pre-accepted and some organizations on which no decisions have been taken;
# the last group should not occur in production but this will check that
# "undecided" organizations are not processed by the mapper
seeded_orgs = ([], [], [])
statuses = (
org_model.Status.PRE_ACCEPTED,
org_model.Status.PRE_REJECTED,
org_model.Status.APPLYING)
for i in range(_TEST_ORGS_PER_STATUS * len(statuses)):
org = org_utils.seedOrganization(
self.program.key(), org_id='org_id_%s' % i,
status=statuses[i % len(statuses)])
org_utils.seedApplication(org.key, self.org_app.key())
seeded_orgs[i % len(statuses)].append(org.key)
# map between organizations are organization admins
self.admin_map = collections.defaultdict(list)
for i in range(_TEST_ORGS_PER_STATUS * _TEST_NUMBER_OF_ORG_ADMINS):
for j in range(len(statuses)):
org_key = seeded_orgs[j % len(statuses)][i % _TEST_ORGS_PER_STATUS]
admin = profile_seeder.seedProfile(
self.program.key(), admin_for=[org_key])
self.admin_map[org_key].append(admin.key)
self.program_messages = self.program.getProgramMessages()
self.pre_accepted_orgs = seeded_orgs[0]
self.pre_rejected_orgs = seeded_orgs[1]
self.applying_orgs = seeded_orgs[2]
# application responses are not seeded for the organizations below
self.no_app_response_orgs = [
org_utils.seedOrganization(
self.program.key(), status=org_model.Status.APPLYING).key]
# set parameters of the MapReduce job
self.params = {
'entity_kind': 'Organization',
'program_key': str(self.program.key())
}
def testDecisionsAreApplied(self):
"""Tests that status of organizations is changed after the job."""
mapreduce_control.start_map(
'ApplyOrgAdmissionDecisions', params=self.params)
test_support.execute_until_empty(
self.taskqueue_stub, queue=mapreduce_control.MAPREDUCE_QUEUE_NAME)
# check that pre-rejected organizations are accepted now
for org_key in self.pre_accepted_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.ACCEPTED)
# check that pre-rejected organizations are rejected now
for org_key in self.pre_rejected_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.REJECTED)
# check that nothing has changed regarding applying organizations
for org_key in self.applying_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.APPLYING)
# check that organizations with no application response are rejected now
for org_key in self.no_app_response_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.REJECTED)
for org_key in self.pre_accepted_orgs:
org = org_key.get()
subject = notifications.DEF_ACCEPTED_ORG % {
'org': org.name,
}
self.assertEmailSent(cc=org.contact.email, subject=subject)
for org_key in self.pre_rejected_orgs:
org = org_key.get()
subject = notifications.DEF_REJECTED_ORG % {
'org': org.name,
}
self.assertEmailSent(cc=org.contact.email, subject=subject)
def testOrgsForAnotherProgram(self):
"""Tests that status of organizations for another program is untouched."""
# seed another program
program = seeder_logic.seed(program_model.Program)
# seed a few pre-accepted and pre-rejected organizations
pre_accepted_orgs = []
for i in range(2):
org = org_utils.seedOrganization(
program.key(), org_id='pre_accepted_org_id_%s' % i,
status=org_model.Status.PRE_ACCEPTED)
pre_accepted_orgs.append(org.key)
pre_rejected_orgs = []
for i in range(3):
org = org_utils.seedOrganization(
program.key(), org_id='pre_rejrected_org_id_%s' % i,
status=org_model.Status.PRE_REJECTED)
pre_rejected_orgs.append(org.key)
mapreduce_control.start_map(
'ApplyOrgAdmissionDecisions', params=self.params)
test_support.execute_until_empty(
self.taskqueue_stub, mapreduce_control.MAPREDUCE_QUEUE_NAME)
# check that pre-accepted organizations are still pre-accepted
for org_key in pre_accepted_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.PRE_ACCEPTED)
# check that pre-rejected organizations are still pre-rejected
for org_key in pre_rejected_orgs:
org = org_key.get()
self.assertEqual(org.status, org_model.Status.PRE_REJECTED)
def testAdminsRejectedForRejectedOrgs(self):
"""Tests that admins for rejected organizations are rejected."""
# seed two organizations; one of them will be rejected
rejected_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.PRE_REJECTED)
org_utils.seedApplication(rejected_org.key, self.org_app.key())
other_org = org_utils.seedOrganization(self.program.key())
org_utils.seedApplication(other_org.key, self.org_app.key())
# seed a profile who is an admin for both organizations
extra_admin = profile_seeder.seedProfile(
self.program.key(), admin_for=[rejected_org.key, other_org.key])
# seed a profile who is an admin for rejected org and a mentor for other org
extra_mentor = profile_seeder.seedProfile(
self.program.key(), mentor_for=[other_org.key],
admin_for=[rejected_org.key])
mapreduce_control.start_map(
'ApplyOrgAdmissionDecisions', params=self.params)
test_support.execute_until_empty(
self.taskqueue_stub, queue=mapreduce_control.MAPREDUCE_QUEUE_NAME)
# check that all admins are rejected
for org_key, admin_keys in self.admin_map.iteritems():
org = org_key.get()
if org.status == org_model.Status.REJECTED:
admins = ndb.get_multi(admin_keys)
for admin in admins:
self.assertIn(org_key, admin.rejected_for)
self.assertNotIn(org_key, admin.mentor_for)
self.assertNotIn(org_key, admin.admin_for)
# check that extra admin is rejected for rejected org
extra_admin = extra_admin.key.get()
self.assertIn(rejected_org.key, extra_admin.rejected_for)
self.assertNotIn(rejected_org.key, extra_admin.mentor_for)
self.assertNotIn(rejected_org.key, extra_admin.admin_for)
# check that extra admin is still an admin for the other org
self.assertIn(other_org.key, extra_admin.mentor_for)
self.assertIn(other_org.key, extra_admin.admin_for)
# check that extra mentor is rejected for rejected org
extra_mentor = extra_mentor.key.get()
self.assertIn(rejected_org.key, extra_mentor.rejected_for)
self.assertNotIn(rejected_org.key, extra_mentor.mentor_for)
self.assertNotIn(rejected_org.key, extra_mentor.admin_for)
# check that extra mentor is still a mentor for the other org
self.assertIn(other_org.key, extra_mentor.mentor_for)
self.assertNotIn(other_org.key, extra_mentor.admin_for)
def testMentorRolesClearedForRejectedOrgs(self):
"""Tests that mentor roles for rejected organizations are cleared."""
# seed two organizations; one of them will be rejected
rejected_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.PRE_REJECTED)
org_utils.seedApplication(rejected_org.key, self.org_app.key())
other_org = org_utils.seedOrganization(self.program.key())
org_utils.seedApplication(other_org.key, self.org_app.key())
# seed a profile who is a mentor for both organizations
other_mentor = profile_seeder.seedProfile(
self.program.key(), mentor_for=[rejected_org.key, other_org.key])
# seed a profile who is a mentor for the rejected organization and
# an administrator for the other organization
other_admin = profile_seeder.seedProfile(
self.program.key(), mentor_for=[rejected_org.key],
admin_for=[other_org.key])
mapreduce_control.start_map(
'ApplyOrgAdmissionDecisions', params=self.params)
test_support.execute_until_empty(
self.taskqueue_stub, queue=mapreduce_control.MAPREDUCE_QUEUE_NAME)
# check that the role for extra mentor is removed
other_mentor = other_mentor.key.get()
self.assertNotIn(rejected_org.key, other_mentor.admin_for)
self.assertNotIn(rejected_org.key, other_mentor.mentor_for)
self.assertNotIn(rejected_org.key, other_mentor.rejected_for)
# check that extra admin is not a mentor but is still an administrator
# for the other organization
other_admin = other_admin.key.get()
self.assertNotIn(rejected_org.key, other_admin.admin_for)
self.assertNotIn(rejected_org.key, other_admin.mentor_for)
self.assertNotIn(rejected_org.key, other_admin.rejected_for)
self.assertIn(other_org.key, other_admin.admin_for)
self.assertIn(other_org.key, other_admin.mentor_for)